我也许在这里挑剔,但如果这个一直困扰我的问题得到一劳永逸的答案,那就太好了......
代表的文本文件:
Line one.
Line two.
Line three.
Line four.
sed
要一致地向此文本文件添加额外的空行,每行需要两个命令。这可以通过以下任何语法来实现:
sed -e '/^$/d' -e '$!G' <file>
...但不是(sed -e '/^$/d' '$!G' <file>
或sed '/^$/d' '$!G' <file>
)sed -e '/^$/d; $!G' <file>
或者sed -e '/^$/d ; $!G' <file>
sed '/^$/d; $!G' <file>
或者sed '/^$/d ; $!G' <file>
我的问题是:
- 上面列出的五种工作语法之间是否有任何真正的区别(通用性?,合规性?...)?
- 理查德·布鲁姆的最新作品命令行和 Shell 脚本圣经
sed -e 's/brown/red/; s/dog/cat/' data1.txt
说在给出以下建议之前使用类似的东西......
命令必须用分号 (;) 分隔,并且第一个命令末尾和分号之间不应有任何空格。
...然后继续完全忽略他自己的建议,-e
根本不使用该选项,并在命令末尾和分号之间添加空格(如上面 #3 的第二个变体所示).. 所以,分号周围的间距有什么真正的区别吗?
- 尽管我在联机帮助页或文档中找不到有关此内容的信息,但我的预感是该
-e
选项应该按照上面的语法#1 中所示的方式使用,并且在命令行上同时使用 和 是多余的-e
。;
我对么?
编辑:我应该在原来的问题中提到这一点以使其更具体;但正如有些人已经指出的那样,在使用branch( b
)或test( t
)命令时,这些细微差别很重要。但有趣的是,注意其他情况,这些情况会产生影响。谢谢!
答案1
这对于一些命令来说确实很重要。
在原始sed
实现中,: foo;bar
、分别定义、b foo;bar
分支t foo;bar
、条件分支到foo;bar
标签。
它甚至曾经是 POSIX 所要求的(我是那个要求放宽要求)。
w foo;bar
并且仍然在所有符合要求的实现中向文件r foo;bar
写入/从文件读取。foo;bar
命令#
(用于注释)、a
、i
、c
(追加、插入、更改)显然不能在同一行上跟另一个命令。
历史sed
实现也不支持}
后面跟着另一个命令。
POSIX 曾经说过你不能有一个;
before }
,尽管在实践中不需要(我也要求放宽这一要求)。
sed -e cmd1 -e cmd2
意味着相当于
sed -e 'cmd1
cmd2'
但实际上,并非所有实现都如此:
sed -e 'a\' -e 'foo\' -e 'bar'
sed -e 's/foo/bar\' -e 'baz/g'
例如。
答案2
让我们使用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...]
但请注意,正如前面提到的,有些命令后面不能跟分号,然后
sed -e ':a' -e 's/x/y/' -e 't a'
是合规的,同时
sed ':a;s/x/y;t a'
虽然不是,但至少在 GNU Sed 中工作是一样的。
我的预感是,(...)在命令行上同时使用-e
和是多余的。;
我对么?
如果您参考问题中的示例,是的。如果只有一个-e
选项,那么只需将其删除即可,一切都是一样的(除非您也使用该
-f
选项(请参阅概要))。但在
sed -e ':a' -e 's/x/y;t a'
和都存在-e
,;
但它们并不多余。
答案3
好处似乎是编辑命令。
sed -e '/first/a This is cool' -e '/second/i also cool' < <(echo first; echo second)
将产生:
first
This is cool
also cool
second
但正在尝试
sed -e '/first/a This is cool ; /second/i also cool' < <(echo first; echo second)
产量
first
This is cool ; /second/i also cool
second
显然将分号解释为附加的一部分。尽管您仍然可以通过单个命令来实现此目的:
sed -e '/first/a This is cool
/second/i also cool' < <(echo first; echo second)
利用硬返回来启动新命令(允许脚本文件正确运行)。
诚然:
sed '
/first/a This is cool
/second/i also cool' < <(echo first; echo second)