awk匹配列中的多个模式

awk匹配列中的多个模式,awk,Awk,要在一列中匹配多个模式,正确的awk语法是什么?具有如下列文件: c11 c21 c31 c12 c22 c32 c13 c23 c33 如何排除第二列中与c21和c22匹配的行 使用grep,可以执行类似的操作(但它没有指定仅在第二列中匹配): 我试过玩awk,但没有效果: > awk '$2 != /c21|c22/' bar.txt c11 c21 c31 c12 c22 c32 c13 c23 c33 > awk '$2 != "c21" || $2 != "c22"'

要在一列中匹配多个模式,正确的
awk
语法是什么?具有如下列文件:

c11 c21 c31
c12 c22 c32
c13 c23 c33
如何排除第二列中与c21和c22匹配的行

使用
grep
,可以执行类似的操作(但它没有指定仅在第二列中匹配):

我试过玩
awk
,但没有效果:

> awk '$2 != /c21|c22/' bar.txt 
c11 c21 c31
c12 c22 c32
c13 c23 c33

> awk '$2 != "c21" || $2 != "c22"' bar.txt 
c11 c21 c31
c12 c22 c32
c13 c23 c33
那么,正确的
awk
语法是什么呢?

使用and(
&&
)而不是or(
|
):

印刷品:

c13 c23 c33
由于c21不等于c22,第2列中带有c21的行将在带有
|
的版本中打印,因为$2不等于
c22
,反之亦然。事实上,不可能打印所有行,因为在任何行中,第2列都不能同时等于c21和c22

$2 != /c21|c22/
是的缩写

$2 != ($0 ~ /c21|c22/)
它将
$2
与将$0与c21或c22进行比较的结果进行比较,该结果为1或0,因此它测试
$2
是否具有除
1
以外的值

$2 != "c21" || $2 != "c22"
测试
$2
是否不等于
c21
$2
是否不等于
c22
,这是一个始终为真的条件。想想看,如果$2是c21,那么第一个条件(
$2!=“c21”
)为假,但第二个条件(
$2!=“c22”
)为真,依此类推,因此
对于
$2
的任何值都始终为真

你想写的是:

awk '$2 !~ /c21|c22/'
或者更有力地说:

awk '$2 !~ /^(c21|c22)$/'
更简单地说(加上同样有力地),真正写出这种情况的方法是:

awk '$2 !~ /^c2[12]$/'
如果你想做一个字符串而不是regexp比较,那么如果它是一个一次性脚本,你可以做这两个操作中的任何一个(我倾向于第一个,因为它的否定符号更少,这让IMHO更清楚):

除此之外:

awk 'BEGIN{split("c21 c22",t); for (i in t) vals[t[i]]} !($2 in vals)'

最后一个是最好的,因为您只需指定一次
$2
,如果您需要进行更多测试,您只需将其他值添加到被拆分的字符串中,这意味着您不能在脚本的后面打破比较逻辑。

是否有任何使用类似grep的符号编写此脚本的速记方法?更改了我对这个非常完整答案的公认答案。感谢您的精彩演练。
awk '$2 !~ /^c2[12]$/'
awk '!($2 == "c21" || $2 == "c22")'
awk '$2 != "c21" && $2 != "c22"'
awk 'BEGIN{split("c21 c22",t); for (i in t) vals[t[i]]} !($2 in vals)'