与awk不等于运算符

时间:2016-09-09 13:59:14

标签: bash if-statement awk

我不确定我在做什么错,但我肯定在我的awk命令中犯了一些错误。

我有两个文件,fileA包含名称

FILEA

Abhi
Roma
GiGi
KaKa

FileB包含名称为

的其他数据
Abhi 23  Pk
DaDa 43  Gk
Roma 33  Kk
PkPk 22  Aa

现在,我尝试打印fileA中不存在的所有名称的详细信息。

for i in `cat FileA` ; do cat FileB | awk '{ if ($1!='$i') print $0_}'>> Result; done

我得到的是

Abhi    23  Pk
DaDa    43  Gk
Roma    33  Kk
PkPk    22  Aa
Abhi    23  Pk
DaDa    43  Gk
Roma    33  Kk
PkPk    22  Aa
Abhi    23  Pk
DaDa    43  Gk

期望的输出

DaDa 43  Gk
PkPk 22  Aa

任何人都可以帮我找出错误。

谢谢

2 个答案:

答案 0 :(得分:3)

为此,您只需要grep

$ grep -vf fileA fileB
DaDa 43  Gk
PkPk 22  Aa

这使用fileA来获取模式。然后,-v反转匹配。

AwkMan很好地解决了为什么你没有正确匹配行。现在,让我们看看您的解决方案需要抛光的地方:

您的代码是:

for i in `cat FileA`
do
    cat FileB | awk '{ if ($1!='$i') print $0_}'>> Result
done

Why you don't read lines with "for"解释得很清楚。所以你需要说出Read a file line by line assigning the value to a variable中描述的内容:

while IFS= read -r line
do
    cat FileB | awk '{ if ($1!='$i') print $0_}'>> Result
done < fileA

然后,你说cat file | awk '...'。为此,awk '...' file就足够了:

while IFS= read -r line
do
    awk '{ if ($1!='$i') print $0_}' FileB >> Result
done < fileA

此外,重定向可以在done的末尾完成,因此您可以获得更清晰的命令:

while IFS= read -r line
do
    awk '{ if ($1!='$i') print $0_}' FileB
done < fileA >> Result

多次调用awk无用,您可以使用FNR==NR trick一起处理两个文件。

现在让我们进入awk。在这里,您希望使用某种变量来比较结果。但是,$iawk无关。

此外,当你有一句话:

awk '{if (condition) print $0}' file

同样地说:

awk 'condition' file

因为{print $0}是条件计算结果为true时要执行的默认操作。

另外,要让awk使用bash变量,您需要使用awk -v var="$shell_var",然后在内部使用var -

总之,你应该说:

while IFS= read -r line
do
    awk -v var="$line" '$1 != var' FileB
done < fileA >> Result

但是由于你循环遍历文件很多次,它会多次打印这些行。这就是为什么你必须一直到这个答案并使用grep -vf fileA fileB

答案 1 :(得分:2)

问题在于,当您想要与字符串进行比较时,该字符串必须在引号之间,否则,它假定该字符串是变量名。

例如:

awk '{ if ($1!=name) print $0_}'

在这种情况下,awk将假设&#34; name&#34;是一个变量,它将为空,因为没有赋值给它,因此,将$ 1与空字符串进行比较。

awk '{ if ($1!="name") print $0_}'

在这种情况下,awk会将$ 1与字符串&#34; name&#34;进行比较。

因此,正确的代码是:

for i in `cat FileA` ; do cat FileB | awk -v var="$i" '{ if ($1!=var) print $0_}'>> Result; done

这也可以,但我认为以前的方式更清楚:

for i in `cat FileA` ; do cat FileB | awk '{ if ($1!="'$i'") print $0_}'>> Result; done

编辑:检查fedorqui答案,了解解决方案中的更好方法