我在使用本网站上提供的答案时遇到一些问题,该问题是关于sed命令用其他两行内容替换空白行的,如果在Mac OS上使用sed命令(对于我来说是10.6.7, ) 是不同的。我认为并非如此,但我想知道本网站上的其他人是否有不同的看法。
我在使用本网站上提供的答案时遇到一些问题,该问题是关于sed命令用其他两行内容替换空白行的,如果在Mac OS上使用sed命令(对于我来说是10.6.7, ) 是不同的。我认为并非如此,但我想知道本网站上的其他人是否有不同的看法。
Answers:
在unix变体之间,shell实用程序的行为确实存在细微差别。有许多UNIX变种,具有复杂的 历史。有诸如POSIX标准及其超集Single UNIX规范之类的标准化工作。如今,大多数系统都实现了POSIX:2001(也称为Single UNIX Specification版本3),并且存在细微的差异和许多扩展。Single Unix规范不是教程,但是如果您已经知道命令的作用,则可以阅读版本3。您可以查阅它,以了解某些功能是标准功能还是特定系统的扩展。
大部分的Unix用户使用Linux,并且未使用任何其他变体。Linux随附GNU实用程序,该实用程序通常对该标准进行了许多扩展。因此,您会发现有很多代码可以在Linux上运行,但不能在其他unices上运行,因为它依赖于这些扩展。
关于sed,请参阅sed单个Unix规范,以获取每个系统应支持的最低标准,有关实现支持的系统手册页,以及有关大多数人使用的GNU sed手册。
GNU sed中的非标准扩展之一是支持同时运行多个命令。例如,此GNU sed程序会打印包含的所有行a
,但会b
变为c
first:
sed -ne '/a/ {s/b/c/g; p}'
{
并且}
实际上是单独的命令,因此要获得完全的可移植性,您需要在单独的行(在文件中)或单独的-e
参数(在命令行)中指定它们。常见的扩展是缺少命令分隔符,{
以及在命令分隔符的使用;
。之前缺少命令分隔符}
是较不常见的扩展。这是符合标准的:
sed -n -e '/a/ {' -e 's/b/c/g' -e p -e '}'
这是非标准的,但通常被接受:
sed -ne '/a/ { s/b/c/g; p; }'
另一个非标准但常见的扩展名是\n
在s
替换文本中使用表示换行符(在正则表达式中使用是标准的)。可移植的方法是在sed脚本中包含反斜杠换行符。另一种常见的扩展是\+
,\?
和\|
在正则表达式来表示一个或更多个,至多一个和交替; 可移植的基本正则表达式没有这些。例如,第一个命令是一种用换行符替换空白连续序列的非便携式方法;第二个命令是符合标准的等效命令。
sed -e 's/ \+/\n/'
sed -e 's/ */\
/'
sed -ne '/a/ { s/b/c/g; p; }'
自2016年版标准以来已成为标准。它总是便携的。见austingroupbugs.net/view.php?id=944&nbn=7
OS X当前带有自2005年以来的FreeBSD sed。以下大多数差异也适用于其他BSD sed版本。
-E
ERE和GNU sed用途的OS X的sed用途-r
。-E
是-r
GNU sed中的别名(在4.2中添加,直到4.3才记录)。较新版本的FreeBSD和NetBSD sed都支持-E
和-r
。OpenBSD sed仅支持-E
。
-i ''
适用于OS X的sed,但不适用于GNU sed。-i
与GNU sed,NetBSD的最新版本,OpenBSD一起使用sed
,但不适用于OS X的sed。-i -e
两者均可使用,但对于FreeBSD而言sed
,将原始文件的备份-e
附加到文件名之后(并且您最多需要将一个表达式传递给sed
)。
GNU sed的解释逸出样序列\t
,\n
,\001
,\x01
,\w
,和\b
。OS X的sed和POSIX sed仅解释\n
(但不解释s
)。
GNU sed会在BRE中解释\|
,\+
和\?
,但OS X的sed和POSIX的不会。\(
,\)
,\{
,和\}
是POSIX BRE。
GNU sed之前可以省略;
或使用换行符,}
但OS X的sed不允许。
i
(插入),a
(附加)和c
(更改)必须在OS X的sed和POSIX的s中加上反斜杠和换行符,但在GNU的sed之后。GNU SED通过插入的文本后面增加一个换行符丢失i
,a
或c
但OS X的sed的没有。例如,sed 1ia
是GNU的替代品sed $'1i\\\na\n'
。
例如,printf a|sed -n p
在OS X的sed中添加换行符,但不在GNU的sed中添加换行符。
OS X的sed不支持I
(不区分大小写)或M
(多行)修饰符。较新版本的FreeBSD sed支持I
。
OS X的sed不支持-s
(--separate
),-u
(--unbuffered
)或-z
(--null-data
)。
GNU sed不支持的一个BSD选项是-a
,它可以w
追加到文件而不是截断文件。
不适用于OS X的sed的GNU sed命令示例:
sed /pattern/,+2d # like `sed '/pattern/{N;N;d;}'`
sed -n 0~3p # like `awk NR%3==0`
sed /pattern/Q # like `awk '/pattern/{exit}1'` or `sed -n '/pattern/,$!p'`
sed 's/\b./\u&/g' # \u converts the next character to uppercase
sed 's/^./\l&/' # \l converts the next character to lowercase
sed -i '1ecat file_to_prepend' file # e executes a shell command
sed -n l0 # 0 disables wrapping
-i -e
在OSX上不起作用。它interpets -e
作为后缀。
-i
,即使为空字符串,也始终需要后缀。所以-i '' -e
应该工作。
-i -e
对两者都起作用”。您的回答表明存在跨平台解决方案。显然没有。
我发现在Linux和Mac上具有相同脚本的最佳方法是:
sed -i.bak -e 's/foo/bar/' -- "${TARGET}" &&
rm -- "${TARGET}.bak"
perl
其-i
来源。perl -Tpi -e 's/foo/bar/' -- "$TARGET"
sed
本身是合规的,因为它做了标准允许(但不是必需的,未指定)的事情。在某些情况下,它不符合要求并且POSIXLY_CORRECT
可以在环境中运行它可以提供帮助。像s/[\n]//g
这样,必须删除反冲和n
字符,但要删除换行符。或N
命令在最后一行的行为。