今天我在网上搜索一个命令,在模式后打印下两行,我遇到了一个我无法理解的awk命令。
$ /usr/xpg4/bin/awk '_&&_--;/PATTERN/{_=2}' input
有人可以解释一下吗?
答案 0 :(得分:37)
有关此处重复的答案,请参阅https://stackoverflow.com/a/17914105/1745001。
答案 1 :(得分:13)
_
在这里被用作变量名称(有效但显然令人困惑)。如果你把它重写为:
awk 'x && x--; /PATTERN/ { x=2 }' input
那么解析会更容易一些。每当/PATTERN/
匹配时,变量将设置为2
(并且不输出该行) - 这是下半部分。第一部分在x
不为零时触发,并递减x
以及打印当前行(默认操作,因为该子句未指定操作)。
最终结果是在模式匹配后立即打印两条线,只要这些线都不匹配模式。
答案 2 :(得分:8)
简单地说,命令在给定的正则表达式表达式匹配后打印多行,不包括匹配的行。
行数{_=2}
中指定行数,如果行匹配_
,则变量PATTERN
设置为2。匹配行后读取的每一行都会导致_
递减。你可以阅读_&&_--
,好像_
大于零,然后减去它,这在匹配后的每一行都会发生,直到_
达到零。使用更合理的名称_
替换变量n
时,这非常简单。
一个简单的演示应该清楚(打印跟随foo
的任何一行的2行:
$ cat file
foo
1
2
3
foo
a
b
c
$ awk 'n && n--;/foo/{n=2}' file
1
2
a
b
所以n
仅在将一行与foo
匹配后设置为2时才为True,然后递减n
并打印当前行。由于awk
短路评估n
仅在n
为真(n> 0)时递减,所以在这种情况下n
唯一可能的值condition{block}
1}}是2,1或0.
Awk具有以下结构awk
,当条件被评估为True时,则对当前记录执行block。如果您未提供块{print $0}
,则使用默认块n && n--;
,因此n
是一个没有块的条件,只有在正则表达式后n&&n--
行的计算结果为True比赛。分号只是为条件/foo/
界定条件$ awk '/foo/{n=3} n && n--' file
foo
1
2
foo
a
b
,使条件明确表示条件没有阻塞。
要打印匹配后的两行,包括您将要执行的匹配:
/usr/xpg4/bin/awk
额外额外:使用/usr/bin/awk
的完整路径这一事实告诉我这个代码是针对Solaris机器的,因为{{1}}完全被破坏了,应该是不惜一切代价避免。
答案 3 :(得分:3)
<强>解释强>
awk
表达式具有以下形式:
condition action; NEXT_EXPRESSION
如果条件为真,则将执行操作。进一步说明,如果condition为true但是省略了action awk
将执行print
(默认操作)。
您的代码中有两个表达式将在每一行输入上执行:
_&&_-- ;
/PATTERN/{_=2}
两者都以;
分隔。正如我所说,如果省略该操作,将发生默认操作print
,与相同:
_&&_-- {print};
/PATTERN/ {_=2}
在您的示例中,_
是一个变量名称,在第一次使用之前由0
初始化,在第一次使用之前 - 由awk自动生成。
第一个条件是(0) && (0)
..导致条件为假的原因是,0 && 0
评估为false
而awk不会打印。
如果找到模式,_
将设置为2
,这使得下一行的第一个条件为(2) && (2)
,之后的下一行为(1) && (1)
作为_
的行在评估条件后递减。两者都在评估true
,而awk将打印这些行。
然而,很好的谜题;)
答案 4 :(得分:2)
奇妙的模糊。将在时间允许时更新。
_
被用作变量名。 &&
是一个逻辑运算符,它有2个真正的动作一起运行。一旦_的值减小到零,&amp;&amp;的下半部分。为false,不生成输出。
print -- "
xxxxx
yyyy
PATTERN
zzz
aa
bbb
ccc
ddd" | awk '_&&_--;/PATTERN/{_=2}'
<强>输出强>
zzz
aa
调试版
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