如何在 awk 程序中一起使用 AND 和 OR?

Sol*_*osa 3 awk text-processing

我有 2 列文件,如:

$ cat data
a4 b1
a4 c2
a4 b4
z4 c2
Run Code Online (Sandbox Code Playgroud)

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

(期望的输出)

a4 b1 matched
a4 c2 matched
a4 b4 -
z4 c2 -
Run Code Online (Sandbox Code Playgroud)

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

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

我得到了 - 对于整个 column3,我想我的 awk 语法错误,或者缺少其他东西 - 以下是结果:

a4 b1 -
a4 c2 -
a4 b4 -
z4 c2 -
Run Code Online (Sandbox Code Playgroud)

Adm*_*Bee 6

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

通过(小)所需的更正,程序将如下所示:

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

它的工作原理如下:

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

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

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

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


αғs*_*нιη 5

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

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


Ed *_*ton 5

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