【问题标题】:Bash If Statement Incorrectly SpecifiedBash If 语句指定不正确
【发布时间】:2021-10-27 19:00:19
【问题描述】:

我没有在 bash 中正确指定我的 If 语句,但我不确定我到底做错了什么。

我有数百名参与者完成了不同数量的研究程序,因此他们拥有不同数量的可用文件。我添加了一个 if 语句来指定在处理过程之后我们应该为每个参与者找到多少个文件。它应该遍历每个参与者,根据 ID 为变量分配 3 到 5 之间的值,然后使用该变量的值来查找一定数量的文件。

# SUBJECTS is a concatenated list of IDs 
for i in ${SUBJECTS}; do

    # Different subjects have a different number of files. 
    # I want to specify how many files bash should look for based on ID.
    # This first if statement should identify whether the current iteration of i matches any of the identified IDs. 
    # If so, it should specify that bash should be looking for 4 files.
    if [[ ${i} -eq "XX001" ||\
          ${i} -eq "XX002" ||\
          ${i} -eq "XX003" ]]; 
    then 
        NFILES=4

    # ... and if any iterations of i match these IDs, bash should look for 3 files
    elif [[ ${i} -eq "XX004" ||\
            ${i} -eq "XX005" ]]; 
    then 
        NFILES=3

    # ... and for everyone else, bash should look for 5 files.
    else
        NFILES=5
    fi

    # Now, for each participant, iterate through the number of files we expect they should have
    for j in `seq -w 1 ${NFILES}` ; do

        # ... and check whether a file of this name exists in this location
        if [ ! -f "${FILEPATH}/FILENAME_${i}_${j}.nii.gz" ]; then

            # If it does not, note which ID and File is missing at the end of this document
            echo "${i}; FILE ${j}" >> ${FILEPATH}/MissingFiles.txt

        fi

    done

done

如果我在没有第一个 If 语句的情况下运行此脚本,它会正确识别参与者的文件存在,但它也会给出很多假阴性(例如,如果参与者只有三个文件,输出将建议文件4 和 5 缺失,即使这是预期的结果)。当我添加 If 语句时,计算机似乎由于某种原因假设所有参与者都满足第一个条件,因此它认为所有参与者都有 4 个文件。

我一直在使用很多其他线程,例如 this onethis one 来寻找解决方案,但运气不佳。非常感谢任何帮助!

【问题讨论】:

  • ShellCheck 警告不要使用 -eq,因为这仅适用于 integer comparisons,并表示要改用 =
  • [[ 中不需要换行符;如果还没有看到]],则解析器知道命令正在继续。
  • 您也可以使用模式匹配,因此if [[ $i == XX00[123] ]] 无需跨越多行即可工作。
  • 不需要seq; for ((j=1; j <= $NFILES; j++)); do.
  • @thatotherguy 感谢您的澄清。我遇到过另一篇提倡使用 -eq 的帖子,但我要么错过了它用于整数的观点,要么没有提到它。

标签: linux bash if-statement conditional-statements


【解决方案1】:

[[ ]] 条件表达式中,-eq 运算符进行数字比较,而不是字符串比较;你想要= 运算符(或等效的==)。

注意:[[ ]][ ](( )) 表达式之间的语法和运算符语义令人困惑。请参阅 this Unix&Linux answerBashFAQ #31。如果您正在编写 bash(即您的脚本不需要能够在 dash 或其他没有 [[ ]] 的 shell 下运行),我建议您完全避免使用 [ ] 并使用 [[ ]]大多数测试,但(( )) 可以用于严格的算术运算。

不过,在这种情况下,由于您是在将一个变量与一组可能的值进行比较,我建议您使用 case 语句。这就是他们的目的。

case "$i" in
    XX001 | XX002 | XX003 )
        NFILES=4 ;;
    XX004 | XX005 )
        NFILES=3 ;;
    ...
    * )
        NFILES=5 ;;
esac

您也可以在此处使用 glob 模式,因此 XX00[123] ) 将匹配“XX001”、“XX002”或“XX003”。

我还建议切换到小写或混合大小写的变量名称,以避免与许多具有特殊含义的全大写名称发生冲突。

【讨论】:

  • 非常感谢您的详细回复!案例解决方案就像一个魅力,我感谢您描述运算符和括号之间的差异。我之前显然没有意识到这一点。
猜你喜欢
  • 2022-08-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-06-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多