Shell无法在IF语句中评估多个条件

时间:2019-12-04 21:16:13

标签: bash shell if-statement

我想基于两个条件将文件分类到文件夹中,但是它不会同时评估这两个条件。条件基于从文本文件(index.txt)中读取的与特定主题相对应的值,并且这些值被编码为0或1

Subid   DX    SEX
XXXX    0      0
YYYY    1      0

代码如下

    #!/bin/sh 
    d=XXXX
    dx=$(awk '{if($1=='$d'){print $2}}' index.txt)
    sex=$(awk '{if($1=='$d'){print $3}}' index.txt)
    if [ "$dx" == "0" ] && [ "$sex" == "0" ];then
     commands
    fi

我尝试使用双括号[[ <condition 1> ]] && [[ <condition 2> ]];,折叠括号if [ <condition1> && <condition2> ];,括号,并使用-eq代替==,但是它们仍然没有评估,也没有错误正在打印。我想念什么?

2 个答案:

答案 0 :(得分:2)

调试外壳程序脚本时最有用的技巧之一是set -x(或使用sh -x运行整个脚本)。这样一来,shell在执行命令时便会打印出与每个命令等效的命令,因此您可以更好地了解实际发生的情况以及它是否符合您的期望。让我们在您的脚本上尝试一下:

$ sh -x reader.sh
+ d=XXXX
++ awk '{if($1==XXXX){print $2}}' index.txt
+ dx=
++ awk '{if($1==XXXX){print $3}}' index.txt
+ sex=
+ '[' '' == 0 ']'

请注意,它会将dxsex都设置为空字符串。并且,如果您查看正在执行的awk脚本,您会看到原因:XXXX周围没有双引号,因此awk将其视为变量名,而不是与之匹配的文字字符串

您可以添加双引号,但这并不是最好的方法。将文字字符串粘贴到可执行代码(在这种情况下为awk脚本)中,可能会将字符串的某些部分误认为是可执行代码,这可能会带来真正的怪异/不良后果。进行此类操作的更好方法是使用awk的-v选项设置变量,然后使用该变量将数据作为数据传递给 。像这样:

$ awk -v d="XXXX" '{if($1==d){print $2}}' index.txt
0

嘿,它打印正确的东西!因此,这是使用该脚本的版本:

#!/bin/sh
d=XXXX
dx=$(awk -v d="$d" '{if($1==d){print $2}}' index.txt)
sex=$(awk -v d="$d" '{if($1==d){print $3}}' index.txt)
if [ "$dx" = "0" ] && [ "$sex" = "0" ];then
    commands
fi

请注意,名为d的awk变量与名为d的shell变量没有内在联系; -v d="$d"位将shell变量复制到同名的awk变量中。另外,在比较中,我将==切换为=,因为这是[ ]中的标准字符串相等运算符。 bash允许==作为同义词,但并非所有的shell都这样做。如果您是专门为bash编写的,则应使用特定的bash shebang行(#!/bin/bash#!/usr/bin/env bash)而不是#!/bin/sh

(实际上,我建议使用bash shebang,因为如果您不清楚标准的shell语法和bash扩展名是什么,那么您可能无论如何都无法移植,因此显式请求bash更加安全。如果这样做的话,最好改用[[ ]]而不是[ ],因为它避免了[ ]表达式所遭受的许多语法怪异。)

答案 1 :(得分:0)

问题不在于您的条件,而是与您的awk设置的变量有关。

尝试以下设置变量:

#!/bin/sh
d=XXXX
dx=$(awk '{if ($1 ~ /'$d'/) print $3}' index.txt)
sex=$(awk '{if ($1 ~ /'$d'/) print $3}' index.txt)
if [ "$dx" = "0" ] && [ "$sex" = "0" ];then
echo "works"
fi