sta*_*one 3 sed regular-expression
我无法理解这个 sed 脚本是如何工作的:
echo -e "Line #1\n\n\n\nLine #2\n\n\nLine #3" | sed '1s/^$//p;/./,/^$/!d'
Run Code Online (Sandbox Code Playgroud)
它抑制重复的空行,例如cat -s
但我有几个问题:
1s/^$//p
?据我了解,即使第一行为空,它也不做任何事情/./,/^$/
只在第一次^$
喜欢之前Line #1\n\n
匹配而不是匹配Line #1\n\n\n
?为了澄清问题 3,我尝试了下一个测试:
echo -e "Line #1\n\n\n\nLine #2\n\n\nLine #3" | sed -n '/#/,/#/p'
结果是:
Line #1
Line #2
Line #3
Run Code Online (Sandbox Code Playgroud)
(所以,它是贪婪的)
但是当我尝试时:
echo -e "Line #1\n\n\n\nLine #2\n\n\nLine #3" | sed -n '/#1/,/#/p'
Run Code Online (Sandbox Code Playgroud)
结果是:
Line #1
Line #2
Run Code Online (Sandbox Code Playgroud)
(现在好像不贪心了)
1s/^$//p
打印第一行,如果它是空的。
/./,/^$/
匹配从第一个非空行到遇到的第一个空行的行。从某种意义上说,正则表达式限定符并不贪婪:sed
不能向前看文件或回溯,因此它必须在结束模式第一次匹配时停止。
在结束行之后,再次开始搜索开始行,因此下一个非空行再次开始范围。实际上,范围匹配连续的非空行,加上后面的第一个空行。
由于范围用作/./,/^$/!d
,所有不匹配的行都将被删除。如果它是空的,这包括第一行,这就是为什么它由第一条规则显式打印。
如果没有1s/^$//p
规则,第一行如果是空的,即使它不是真正的“重复”,也会被删除。
$ echo $'\nfoo' | sed '1s/^$//p;/./,/^$/!d'
foo
$ echo $'\nfoo' | sed '/./,/^$/!d'
foo
$
Run Code Online (Sandbox Code Playgroud)
在您的测试中,范围/#/,/#/
有点不同,因为它以相同的模式开始和结束。Line #1
匹配开始模式,(所以中间的空行被打印)Line #2
匹配结束的模式,(后面的空行不是)Line #3
,范围再次开始。
在另一个中,起始模式是/#1/
,但只在输入中找到一次。