【问题标题】:not equal to operator with awk不等于带有 awk 的运算符
【发布时间】:2017-01-17 17:00:16
【问题描述】:

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

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

文件A

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

谁能帮我找出错误。

谢谢

【问题讨论】:

  • 在将您的代码更新为while IFS= read -r i; do awk -v i="$i" '$1 != i {print $0}' FileB; done < FileA > Result 后,如有必要,更新您的问题。 (见Bash FAQ 001。)
  • 像我这样的人请注意:当您在 awk 表达式中有 != 时,请使用单引号' != ' 而不是双引号 " != "

标签: bash if-statement awk


【解决方案1】:

为此你只需要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} 是在条件评估为真时执行的默认操作。

另外,要让 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

【讨论】:

  • @Angelo 看详细解释。
【解决方案2】:

问题是当你想和一个字符串进行比较时,那个字符串必须在引号之间,否则,它假定这个字符串是一个变量名。

例如:

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

在这种情况下,awk 将假定“name”是一个变量,该变量将为空,因为没有为其分配任何值,因此,将 $1 与一个空字符串进行比较。

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

在这种情况下,awk 会将 $1 与字符串“name”进行比较。

因此,适合您的正确代码是:

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 答案以获得更好的解决方案

【讨论】:

  • 不,因为我在cat file 不是一个好建议。既不以这种方式循环文件。看我的回答。
  • 我同意这不是一个好的建议,但他想知道 awk 的问题是什么。我只限于回答这个问题。
  • 是的,我同意这一点,并 +1 以获得很好的解释。然而,指出一个更好的方法会让你的答案更加闪耀:)
  • 谢谢,我会在回答中提到你,因为你已经解释了更好的方法
猜你喜欢
  • 2011-05-04
  • 2012-09-03
  • 2016-07-29
  • 2014-03-22
  • 2012-06-19
  • 2011-08-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多