echo 'foo bar baz quux' | sed -e 's/ /\'$'\n/g'
或(@ ghoti的建议,使其更容易阅读):
echo 'foo bar baz quux' | sed -e $'s/ /\\\n/g'
然而,当我尝试反向转换换行到空格时,它不起作用:
echo -e "foo\nbar" | sed -e 's/\'$'\n/ /g'
仅更改\n
的更简单方法也不起作用:
echo -e "foo\nbar" | sed -e 's/\n/ /g'
这里有一个相关的答案:https://superuser.com/questions/307165/newlines-in-sed-on-mac-os-x,Spiff的详细答案(在页面末尾),但应用相同的逻辑并没有解决问题。
这是在OSX上运行的一种方式(通过http://www.benjiegillam.com/2011/09/using-sed-to-replace-newlines/):
sed -e ':a' -e 'N' -e '$!ba' -e 's/\n/ /g'
然而,我仍然很好奇为什么扭转原来的方法并不起作用。
更新:这里是如何让它使用两行(解决方案是使用N
嵌入换行符):
echo -e "foo\nbar\n" | sed -e 'N;s/\n/ /g'
替代解决方案(详见@ghoti的完整答案):
echo -e "foo\nbar\n" | sed -n '1h;2,$H;${;x;s/\n/ /gp;}'
但是,这个解决方案似乎比问题陈述中建议的慢一点(注意这些命令的顺序很重要,因此尝试以不同的顺序测试它们可能是有意义的):
time seq 10000 | sed -n '1h;2,$H;${;x;s/\n/ /gp;}' > /dev/null
time seq 10000 | sed -e ':a' -e 'N' -e '$!ba' -e 's/\n/ /g' > /dev/null
答案 0 :(得分:1)
sed
的GNU手册页包括:
正常表达
应该支持POSIX.2 BRE,但由于性能问题,它们并不完全。正则表达式中的
\n
序列与换行符匹配,对\a
,\t
和其他序列也是如此。
sed
的Mac OS X手册页包括:
Sed正则表达式
默认情况下,
sed
中使用的正则表达式是基本正则表达式(BRE,有关详细信息,请参阅re_format(7)),但如果{{1}可以使用扩展(现代)正则表达式给出了标志。此外,-E
对正则表达式添加了以下两个:
在上下文地址中,除反斜杠(
sed
)或换行符之外的任何字符都可用于分隔正则表达式。此外,在分隔字符前加上反斜杠字符会导致字符被字面处理。例如,在上下文地址\
中,RE分隔符为\xabc\xdefx
,第二个x
代表自身,因此正则表达式为x
。- 醇>
转义序列
abcxdef
匹配嵌入在模式空间中的换行符。但是,您不能在地址或替换命令中使用文字换行符。
这些不能说,但似乎是这种情况,在\n
命令中,s/regex/new/
部分是正则表达式,但是regex
部分不是。在替换材料中,您必须使用new
后跟换行符来嵌入换行符。在搜索材料(\
)中,您可以使用regex
。
另请注意,\n
适用于行。默认情况下,除了正则表达式元字符sed
之外,模式空间末尾的换行几乎是无法匹配的。你不能通过匹配来删除该换行符。但是,您可以在模式空间中使用多行,然后可以使用$
模式匹配嵌入的换行符。
答案 1 :(得分:1)
您的问题似乎是“为什么原始方法(将空格转换为换行符)的反转不起作用?”。
在sed中,换行符更多的是记录分隔符而不是行的一部分。考虑$
,模式空间末尾的null,位于行的最后一个字符之后,并不是每行的换行符。
使用换行符的Sed命令,例如H
和N
甚至s
,在newline-as-record-separator的范围之外。您要替换的记录介于换行符之间。
为了替换换行符,您需要使用N
,H
等将其置于模式空间中。
所以这是一个选择。
printf 'foo\nbar\nbaz\n' | sed -n '1h;2,$H;${;x;s/\n/ /gp;}'
我们的想法是,我们将所有行都附加到保持缓冲区,然后在文件末尾,将保持缓冲区移回模式空间进行替换,并一次性用空格替换换行符。 / p>
1h;2,$H
构造避免了输出开头的空白,这是由在H
的每一行数据之前附加的换行引起的。
答案 2 :(得分:0)
当我被OSX sed
的特殊性所阻碍时,我倾向于依赖的几个替代方案是tr
和perl
。
echo -e "foo\nbar" | tr '\n' ' '
foo bar
echo -e "foo\nbar" | perl -pe 's/\n/ /'
foo bar