【问题标题】:for loop do not break in shell script while comparing variable value populated from awk比较从 awk 填充的变量值时,for 循环不会中断 shell 脚本
【发布时间】:2023-04-07 08:36:02
【问题描述】:

我正在尝试使用管道分隔符验证文件中的数据。我仍然需要针对所有检查条件进行处理。当验证失败时,不应进行进一步验证。需要从循环中跳过。即使满足条件,我也无法确定为什么中断(或退出)不起作用。

encoding_details 变量将从配置表中填充数据并保存单个文件的字段详细信息。根据配置,这些详细信息集对于每个文件都是动态的。

1-memid-ID|2-memfirstname-NAME|3-memlastname-NAME

值代表列位置-列名-列类型

下面是正在进行中的代码块。放置评论以突出问题

#!/bin/sh

#initiat variables here

retval=0 #this is a variable related with issue

#get configuration details from the table

encrpt_avoid_flag=Y

#extract all files in loop 
#get part of file_name to related configuration
#start validation for each file

#change directory to work on files now
cd  $directy_with_files;

echo "Initiating a process to read files..."
 
extractfilelist=`ls *.txt 2>/dev/null`; 
for file in $extractfilelist
do 
    #now get details of columns to be encrypted for a file 
    encoding_details=`<populated using sqlquery>`   
    
    if [[ -z $encoding_details ]]
    then
        # lets keep this output in a log file - need to work on it
        echo "WARNING: Encoding details not found for file: ${file}"
        echo "Skipping the file from validation scope..." 
    else 
        IFS="|" read -a encoding_column <<< $encoding_details 

        for column in "${!encoding_column[@]}"
        do 
            IFS="-" read -a encoding_column_detail <<< ${encoding_column[$column]}
            column_order=${encoding_column_detail[0]}
            column_name=${encoding_column_detail[1]}
            encoding_type=${encoding_column_detail[2]}
            
            awk -F'|' -v p_column_order="$column_order" -v p_encoding_type="$encoding_type" -v p_encrpt_avoid_flag="$encrpt_avoid_flag" '
            { 
                if ((p_encoding_type == "ID" || p_encoding_type == "NAME") && p_encrpt_avoid_flag == "Y") 
                { 
                    if ($p_column_order != "Blinded" && p_encoding_type == "NAME")
                    {
                        print 1; #this is an error condtion
                        exit;
                    }
                } 
            }' $file | 
            while read retval
            do
                if [ $retval -gt 0 ]
                then
                    echo "ERROR: encryption failed. Please find details below..."
                    echo "column name    : "$column_name 
                    echo "column position: "$column_order
                    echo "file_name      : "$file
                    exit #this exit do not works
                fi
            done
        if [ $retval -gt 0 ]
        then
            break #issue - this break do not work. while printing values inside the if block $retval shows 1 and output get printed as well
        fi
        done #end for column (encoding_column)
    fi #encoding details check end
    if [ $retval -gt 0 ]
    then
        break #issue - this break do not work here as well. while printing values inside the if block $retval shows 1 and output get printed as well
    fi
done #end of file loop
echo "finally : $retval" #and at then end value printed for retval variable is 0? it was 1 when error occoured

【问题讨论】:

  • 您能否将其缩减为重现您遇到的问题的尽可能小的代码段?完整的测试输入,没有像 SQL 查询这样的占位符。否则是不可能复制的。此外,您使用的是 /bin/sh,但在您的代码中使用了诸如 [[ ... ]] 之类的 Bashism - 切换到 /usr/bin/env bash 以使用 Bash。
  • 更多解释见minimal reproducible example
  • 当然,我会在另一篇文章中尝试制作可能的小代码块。如果我错过了 awk 等其他部分的内容,我只是想给出一个整体的想法。谢谢!
  • 阅读mywiki.wooledge.org/BashFAQ/001,尤其是“输入源选择”下关于如何在循环中读取命令输出的部分。如果您将脚本复制/粘贴到 shellcheck.net 中,它会告诉您有关脚本的问题和其他问题。

标签: shell loops awk break


【解决方案1】:

问题是你所有的breaks 都依赖于$retval 的值,而这在各自的作用域中是不存在的。 exit 似乎不起作用的原因是,仅退出了 while 循环,该循环存在于从stdin 读取awk 输出的单独进程中。考虑以下最小示例:

#!/bin/sh

echo 1 | 
while read retval
do
    if [ $retval -gt 0 ]
    then
        echo "retval is greater than 0"
        exit # this exits only the while loop which is in a separate process
        echo "This does not print"
    fi
done

# retval does not exist in this scope
echo retval: [$retval]

这将为您提供以下输出:

retval is greater than 0
retval: []

如您所见,exit 正在退出while 循环,而$retval 在相关代码块之后没有任何值。

【讨论】:

    猜你喜欢
    • 2013-12-14
    • 2012-06-28
    • 2016-08-15
    • 2018-01-07
    • 1970-01-01
    • 2021-06-21
    • 1970-01-01
    • 2015-06-16
    • 2022-01-26
    相关资源
    最近更新 更多