解释awk命令
今天我正在寻找一个命令在网上打印下两行后,我遇到了一个awk命令,我无法理解。
$ /usr/xpg4/bin/awk '_&&_--;/PATTERN/{_=2}' input
有人可以解释吗?
_
在这里被用作variables名(有效但显然令人困惑)。 如果您将其重写为:
awk 'x && x--; /PATTERN/ { x=2 }' input
那么parsing起来会容易一点。 每当/PATTERN/
匹配时,variables被设置为2
(并且该行不被输出) – 这是下半部分。 第一部分在x
不为零时触发,并减lessx
以及打印当前行(缺省操作,因为该子句不指定操作)。
最终的结果是在模式匹配后立即打印两行,只要这两行中的任何一行都不符合模式。
简单地说,在给定的正则expression式expression式匹配不包括匹配的行之后,该命令会打印多行。
行数在块{_=2}
指定,如果行匹配PATTERN
,则variables_
设置为2。 在匹配行之后读取的每一行都会导致_
递减。 你可以阅读_&&_--
就好像_
大于零,然后减去1,匹配后的每一行都会发生这种情况,直到_
命中零。 当你用一个更明智的名字如n
replacevariables_
时,这很简单。
一个简单的演示应该清楚(打印任何符合foo
行foo
的两行):
$ cat file foo 1 2 3 foo a b c $ awk 'n && n--;/foo/{n=2}' file 1 2 a b
所以当n
与foo
匹配后设为2时, n
仅为真,然后递减n
并打印当前行。 由于awk
具有短路评估, n
只在n
为真(n> 0)时递减,所以在这种情况下对于n
的唯一可能值是2,1或0。
Awk具有以下结构condition{block}
并且当条件被评估为True时,对当前logging执行block。 如果你不提供一个块awk
使用默认块{print $0}
所以n && n--;
是在正则expression式匹配后没有块的情况下,只有n
行的值为真。 分号只是为了条件n&&n--
为条件/foo/
划分条件/foo/
明确规定条件没有阻塞。
要打印比赛之后的两条线,包括比赛,你应该这样做:
$ awk '/foo/{n=3} n && n--' file foo 1 2 foo a b
额外的:使用/usr/xpg4/bin/awk
的完整path的事实告诉我这个代码是为Solaris机器devise的,因为/usr/bin/awk
已经完全损坏了,应该不惜一切代价避免。
奇妙的隐晦。 时间允许时更新。
_
正被用作variables名称。 &&
是一个逻辑运算符,有两个真正的动作一起运行。 一旦_的值减到零,&&的后半部分就是假的,没有输出。
print -- " xxxxx yyyy PATTERN zzz aa bbb ccc ddd" | awk '_&&_--;/PATTERN/{_=2}'
产量
zzz aa
debugging版本
print -- " xxxxx yyyy PATTERN zzz aa bbb ccc ddd" | awk '_&&_--;{print "_="_;print _&&_};/PATTERN/{_=2;print "_="_ }'
产量
_= 0 _= 0 _= 0 _= 0 _=2 zzz _=1 1 aa _=0 0 _=0 0 _=0 0 _=0 0
说明
awk
expression式具有以下forms:
condition action; NEXT_EXPRESSION
如果条件是真的,则将执行动作。 进一步注意,如果条件为真,但操作被省略, awk
将执行print
(默认操作)。
你的代码中有两个expression式会在每行input中执行:
_&&_-- ; /PATTERN/{_=2}
两者相隔一个;
。 正如我所说的,如果省略了这个动作,就会发生默认的动作print
,就像下面这样 :
_&&_-- {print}; /PATTERN/ {_=2}
在你的例子中, _
是一个variables名,它在第一行input前被0
初始化,在awk中被自动初始化。
第一个条件是(0) && (0)
..什么结果是错误的,因为0 && 0
评估为false
,awk不会打印。
如果find了模式, _
将被设置为2
,这使得第一个条件是(2) && (2)
在下一行和(1) && (1)
在该行之后的下一行,因为_
在状况正在评估。 两者都评估为true
,awk将打印这些行。
然而,很好的谜题;)