Mac OS X 上 sed 中的换行符

Iva*_*iao 59 mac bash regex sed macos

我发现这\n在 Mac OS X 下的 sed中不起作用。具体来说,假设我想将由单个空格分隔的单词分成几行:

# input
foo bar
Run Code Online (Sandbox Code Playgroud)

我用,

echo "foo bar" | sed 's/ /\n/'
Run Code Online (Sandbox Code Playgroud)

但结果是愚蠢的,\n是逃不掉的!

foonbar
Run Code Online (Sandbox Code Playgroud)

在向谷歌咨询后,我找到了一个解决方法

echo 'foo bar' | sed -e 's/ /\'$'\n/g'
Run Code Online (Sandbox Code Playgroud)

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

Ahm*_*sih 36

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


要使用它sed代替gsed,brew 会在您安装后打印以下说明:

GNU "sed" has been installed as "gsed".
If you need to use it as "sed", you can add a "gnubin" directory
to your PATH from your bashrc like:

    PATH="/usr/local/opt/gnu-sed/libexec/gnubin:$PATH"
Run Code Online (Sandbox Code Playgroud)

也就是说,将以下行附加到您的 ~/.bashrc 或 ~/.zshrc:

export PATH="/usr/local/opt/gnu-sed/libexec/gnubin:$PATH"
Run Code Online (Sandbox Code Playgroud)

  • 这是一个丑陋的解决方法。它没有解释为什么 OS X 上的 `sed` 表现得如此,并且做出了错误的假设,即 `gnu-sed` 更正确。不要成为 GNU 上瘾者并坚持 POSIX 标准以避免长期出现问题。 (4认同)

Lri*_*Lri 31

这些也可以:

echo 'foo bar' | sed 's/ /\
/g'
Run Code Online (Sandbox Code Playgroud)

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

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

OS X 的 sed 不会\n在替换模式中进行解释,但您可以使用以换行符开头的文字换行符。在$'\n'运行 sed 命令之前,外壳用文字换行符替换。

  • 为什么 `sed $'s/ /\\\n/g'` 可以工作,而 `sed $'s/\\\n/ /g'` 不行? (5认同)
  • @alec 即使在 linux/unix 中也不能使用 `sed` 来删除换行符,因为它在每个换行符处进行解析/分割。如果你在 linux/unix 中运行它,它也不会执行任何操作: `echo -e 'foo\nbar' | sed 's/\n//'` (2认同)

Spi*_*iff 12

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

该参数最终成为熟悉的 seds/ / /g格式的字符串。

该字符串由两部分创建,一个接一个。

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

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

's/ /\'部分去除了单引号,但其他方式就像它在命令行上看到的那样传递给 sed。也就是说,反斜杠不会被 bash 吃掉,而是传递给 sed。

$'\n/g'部分获得美元符号和单引号,\n并被转换为换行符。

总之,论点变成

s/ /\ newline/g

[蛮好玩的。花了一段时间才解开那个。+1 一个有趣的问题。]


gee*_*aur 7

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

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

  • `'...'` 是一种 shell 引用;`$'...'` 是另一个。还有 `"..."` 和 `\x` 来引用单个字符。您可以将它们组合在一个单词中,这就是在那里所做的,从普通的 `''` 字符串切换到一个 `$''` 字符串以翻译 `\n`。至于其余的,它正在构建一个 `sed` 命令(`s/text/replacement/flags`)。在这种情况下,命令将启动,在末尾包含一个反斜杠以保护 `$'\n/g'` 附加的文字换行符。结果是用换行符替换所有(`/g` 标志)空格。 (2认同)

wis*_*cky 7

很容易直观地看到正在发生的事情。只需回显字符串即可!

echo 's/$/\'$'\n/g'
Run Code Online (Sandbox Code Playgroud)

结果是

s/$/\
/g
Run Code Online (Sandbox Code Playgroud)

这相当于s/$/\newline/g

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