请解释一下sed脚本

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 但我有几个问题:

  1. 为了什么1s/^$//p?据我了解,即使第一行为空,它也不做任何事情
  2. 这是否/./,/^$/只在第一次^$喜欢之前Line #1\n\n匹配而不是匹配Line #1\n\n\n
  3. 默认情况下,sed 中的范围不是贪婪的吗?

为了澄清问题 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)

(现在好像不贪心了)

ilk*_*chu 6

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/,但只在输入中找到一次。