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)'