我不确定我在做什么错,但我肯定在我的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
任何人都可以帮我找出错误。
谢谢
答案 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
。在这里,您希望使用某种变量来比较结果。但是,$i
与awk
无关。
此外,当你有一句话:
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答案,了解解决方案中的更好方法