如何在 awk 程序中同时使用 AND 和 OR?

如何在 awk 程序中同时使用 AND 和 OR?

我有 2 列文件,例如:

$ cat data
a4 b1
a4 c2
a4 b4
z4 c2

我想匹配两列,例如如果(column1 = a4 and column2 = b1)OR(column1 = a4 and column2 = c2) 那么第 3 列中的输出应该是

(期望输出):

a4 b1 matched
a4 c2 matched
a4 b4 -
z4 c2 -

所以我尝试将我的逻辑合并到 1liner awk 中:

$ awk '{print $1, $2, (($1 = a4 && $2 = b1) || ($1 = a4 && $2 = c2) ? "a4-matched" : "-")}' data

我得到 - 对于整个第三列,我想我有错误的 awk 语法,或者缺少其他东西 - 下面是结果:

a4 b1 -
a4 c2 -
a4 b4 -
z4 c2 -

答案1

您几乎就在那里,但您似乎引入了语法错误:$1=a4不会检查第一列是否等于,而是将变量a4的内容(未定义,因此为空)分配给第一列,从而覆盖其内容(您已经打印了,所以您没有注意到)并且还评估为“假”,因为未初始化的变量评估为“假”。您的其他比较也是如此。这就是为什么你永远不会将“匹配”条件视为“true”。awka4

经过(少量)所需的更正后,程序将如下所示:

awk '{if (($1=="a4" && $2=="b1") || ($1=="a4" && $2=="c2")) $3="matched"; else $3="-"} 1' data.txt 

其工作原理如下:

  • 对于每一行,它都会检查您提到的条件是否满足,并添加一个第三$3通过设置为 或 来从-列到行matched
  • 然后它将打印当前行,包括所做的任何修改。这就是看似流浪1规则块之外 -awk如果遇到规则之外评估为“true”的条件,将打印当前行,包括之前的任何修改。

请注意,上面的程序是为了易于理解和演示这一点而明确编写的。在您的情况下可以缩短它,因为对于以下两种“允许”的情况,条件$1是相同的$2

awk '{if ($1=="a4" && ($2=="b1" || $2=="c2")) $3="matched"; else $3="-"} 1' data.txt

另请注意,修改任何字段都将导致awk使用输出字段分隔符(默认为一个空格)从其各个字段重建行,因此如果输入字段被多个空格分隔,则原始格式将被破坏。如果这是一个问题,您应该采用您在尝试中已经选择的“附加”策略,尽管您应该打印而不是.$0, ( your conditional string )$1, $2, ( your conditional string )

答案2

$ awk '{print $0, ($1=="a4" && ($2 ~ /^(b1|c2)$/) ? "matched" : "-")}' file
a4 b1 matched
a4 c2 matched
a4 b4 -
z4 c2 -

答案3

您不需要检查$1两次,检查一次,因为两种情况下的条件相同,并对$2不同的选项进行多次检查。请注意,分配新字段将导致使用默认值(单个空格字符)awk重建字段,如果输入中有任何空格,这将导致将连续的空格压缩为一个。$0OFS

awk '{ print $0, ($1=="a4" && ($2=="b1" || $2=="c2")?"matched":"-") }' infile

相关内容