我有 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”。awk
a4
经过(少量)所需的更正后,程序将如下所示:
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
重建字段,如果输入中有任何空格,这将导致将连续的空格压缩为一个。$0
OFS
awk '{ print $0, ($1=="a4" && ($2=="b1" || $2=="c2")?"matched":"-") }' infile