“sed -e”和用分号分隔多个命令之间的区别

com*_*ium 4 sed options posix

我可能是在这里挑毛病,但是让这个一直困扰我的问题一劳永逸地回答真是太好了......

reprex 的文本文件:

Line one.
Line two.

Line three.
Line four.
Run Code Online (Sandbox Code Playgroud)

要始终向该文本文件添加额外的空行sed,每行需要两个命令。这可以通过以下任何一种语法来实现:

  1. sed -e '/^$/d' -e '$!G' <file>...但不是(sed -e '/^$/d' '$!G' <file>sed '/^$/d' '$!G' <file>
  2. sed -e '/^$/d; $!G' <file> 或者 sed -e '/^$/d ; $!G' <file>
  3. sed '/^$/d; $!G' <file> 或者 sed '/^$/d ; $!G' <file>

我的问题是:

  1. 上面列出的五种工作语法中的任何一种之间是否有任何真正的区别(通用性?,合规性?...)?
  2. 理查德·布鲁姆 (Richard Blum) 的最新命令行和 Shell 脚本圣经sed -e 's/brown/red/; s/dog/cat/' data1.txt在提出以下建议之前要使用类似的东西......

命令必须用分号 (;) 分隔,并且第一个命令的末尾和分号之间不应有任何空格。

...然后继续完全忽略他自己的建议,根本不使用该-e选项,还在命令末尾和分号之间添加空格(如上面#3 的第二个变体所示)。所以,分号周围的间距有什么真正的区别吗?

  1. 尽管我在联机帮助页或文档中找不到关于此的信息,但我的预感是该-e选项的使用方式如上面的语法编号 #1 所示,并且在命令行上同时使用-e;是多余的。我对么?

编辑:我应该在我原来的问题中提到这一点,以使其更具体;但正如一些人已经指出的那样,在使用 branch ( b) 或 test ( t) 命令时,这些细微差别会很重要。但有趣的是要注意其他情况,当这些情况会有所不同时。谢谢!

Qua*_*odo 6

让我们使用Sed POSIX 标准来回答这些问题。

分号周围的间距有什么真正的区别吗?

除了 {...}、a、b、c、i、r、t、w、: 和 # 之外的编辑命令可以跟一个分号、可选的空白字符和另一个编辑命令。

因此/^$/d ; $!G不合规,但合规/^$/d; $!G。但我确实想知道是否有任何现代 Sed 实现会偶然发现。

上面列出的三种语法中的任何一种之间是否有任何真正的区别(通用性、合规性...)?

否(分号前有空格的除外,如上所述)。这在概要中很清楚:

sed [-n] script [file...]  
sed [-n] -e script [-e script]... [-f script_file]... [file...]
Run Code Online (Sandbox Code Playgroud)

但是,请注意,正如前面提到的,某些命令后面不能跟分号,然后

sed -e ':a' -e 's/x/y/' -e 't a'
Run Code Online (Sandbox Code Playgroud)

是合规的,而

sed ':a;s/x/y;t a'
Run Code Online (Sandbox Code Playgroud)

不是,但至少在 GNU Sed 中工作相同。

我的预感是 (...)在命令行上同时使用-e;是多余的。我对么?

如果您参考问题中的示例,是的。如果只有一个-e 选项,则只需删除它,它都是一样的(除非您也使用该 -f选项(请参阅概要))。但在

sed -e ':a' -e 's/x/y;t a'
Run Code Online (Sandbox Code Playgroud)

双方-e;都存在,但它们不是多余的。


Sté*_*las 6

它对一些命令很重要。

在原始sed实现中: foo;barb foo;bart foo;bar分别定义了分支、条件分支到foo;bar标签。

它甚至曾经是 POSIX 所要求的(我是要求放宽要求的人)。

w foo;bar并且r foo;bar仍然foo;bar在所有符合要求的实现中写入/读取文件。

#命令(征求意见)aic(追加,插入,修改)显然不能跟着在同一行另一个命令。

历史sed实现也不支持}后跟另一个命令。

POSIX 过去常说你不能有一个;}尽管在实践中不需要(我也要求放宽这个要求)。

sed -e cmd1 -e cmd2
Run Code Online (Sandbox Code Playgroud)

意味着等价于

sed -e 'cmd1
cmd2'
Run Code Online (Sandbox Code Playgroud)

但实际上,在所有实现中,情况并非如此:

sed -e 'a\' -e 'foo\' -e 'bar'
sed -e 's/foo/bar\' -e 'baz/g'
Run Code Online (Sandbox Code Playgroud)

例如。