Mac OS X上的sed换行符


44

我发现\n在Mac OS X下的sed 中不起作用。特别是,说我想将由单个空格分隔的单词分成几行:

# input
foo bar

我用,

echo "foo bar" | sed 's/ /\n/'

但是结果是愚蠢的,\n没有逃脱!

foonbar

向Google咨询后,我找到了一种解决方法

echo 'foo bar' | sed -e 's/ /\'$'\n/g'

看完这篇文章后,我仍然不明白什么\'$'\n/g'意思。有人可以向我解释一下吗,或者还有其他方法可以做到吗?谢谢!


这可能也可以工作:echo "foo bar" | tr ' ' '\n'
glenn jackman 2011年

3
谢谢你的建议。但目前我仅以上述情况为例,我确实需要知道如何对进行转义\n
Ivan ZG Xiao

Answers:


27

你可以brew install gnu-sed和替换调用sedgsed

如果您不想在“ g”之前加上sed,可以brew install gnu-sed --with-default-names直接致电sed

(编辑:更新了冲泡标志,帽子提示到了Clément。)


(最后对我来说)在所有平台上使用相同的软件要比处理Mac版本的每个特性都容易。当心,该选项现在--with-default-names没有 --default-names。但是,此选项没有工作在我安装的,所以我不得不把alias gsed=sed~/.profile让它工作。
2015年

4
这是一个丑陋的解决方法。它没有解释为什么sed在OS X上会表现出这种方式并做出gnu-sed更正确的错误假设。不要成为GNU上瘾者,而要坚持POSIX标准,从长远来看可以避免出现问题。
octosquidopus,2015年

这就是Apple应该如何使其操作系统默认运行的方式。为什么要使用程序名称,然后使其工作方式有所不同?我因为这个而浪费了一个小时...
rascio '17

@rascio-因为OS X类似于BSD,而Linux类似于Linux。
iAdjunct

@rascio我想您会发现GNU sed是新来者;BSD sed的历史可以追溯到1979年(请参见en.wikipedia.org/wiki/Version_7_Unix)。
邓肯·拜恩18'Sep

24

这些也可以工作:

echo 'foo bar' | sed 's/ /\
/g'

echo 'foo bar' | sed $'s/ /\\\n/g'

lf=$'\n'; echo 'foo bar' | sed "s/ /\\$lf/g"

OS X的sed不会\n在替换模式中解释,但您可以使用文字换行符,并在其后加上换行符。在$'\n'运行sed命令之前,shell将用文字换行符替换。


4
为什么sed $'s/ /\\\n/g'起作用,但不起作用sed $'s/\\\n/ /g'
亚历克·雅各布森

1
@alec您sed甚至不能在linux / unix中使用它来删除换行符,因为它在每个换行符处进行了解析/拆分。如果您在linux / unix中运行它,它也不会做任何事情:echo -e 'foo\nbar' | sed 's/\n//'
wisbucky

10

您找到的解决方法将单个参数字符串传递给sed -e

该参数最终是熟悉的sed s/ / /g格式的字符串。

该字符串分为两个部分,一个接一个。

第一部分以'...'形式引用。

第二部分以$'...'形式引用。

's/ /\'部分的单引号被去除,否则直接传递给sed,就像在命令行上一样。也就是说,bash不会被bash吃掉,而是传递给sed。

$'\n/g'零件将获得美元符号并去除单引号,然后\n将其转换为换行符。

总之,论点变成

s / / \ newline/ g

[那很有趣。花了一些时间来解开它。+1提出一个有趣的问题。]


7

该表达式$'...'bash-ism,它会...扩展标准的转义序列。钍\'它只是意味着一个反斜杠随后引述节结束前,产生的字串s/ /\。(是的,您可以在字符串中间切换引号;它不会结束字符串。)

POSIX标准sed仅接受\n作为搜索模式的一部分。OS X使用sed严格符合POSIX 的FreeBSD ;像往常一样,GNU增加了一些额外的东西,然后Linux用户都认为是某种“标准”(如果他们中的任何一个都有标准流程,可能会给我留下深刻的印象)。


现在我了解了这一$'...'部分。但是...是什么s/ /\ ?你是什么意思switch quoting
伊万·赞

2
'...'是一种shell引用;$'...'是另一个。还有"..."\x引用单个字符。您可以将它们组合成一个单词(即在其中所做的事情),从普通''字符串切换为$''字符串以翻译\n。至于其余的,它正在建立一个sed命令(s/text/replacement/flags)。在这种情况下,将启动命令,并在末尾$'\n/g'添加反斜杠以保护附加的文字换行符。结果是/g用换行符替换所有(标志)空格。
geekosaur 2011年

1

从视觉上很容易看到发生了什么。只需回显字符串!

echo 's/$/\'$'\n/g'

结果是

s/$/\
/g

相当于 s/$/\newline/g

如果在之前没有多余\的内容newline,shell会newline过早将解释为命令的结尾。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.