使用 POSIX sed 连接行

aaa*_*aaa 4 sed posix newlines

我正在尝试使用 POSIX sed 加入行。

使用 GNU sed(没有 --posix),这可以按预期工作:

$ sed ':a; N; s/\n//; b a' <<< $'a\nb\nc'
abc
Run Code Online (Sandbox Code Playgroud)

但是如果我使用 --posix 我没有输出。

为什么会这样,否则我该怎么做?

Sté*_*las 5

这是一份工作paste

printf '%s\n' a b c | paste -sd '\0' -
Run Code Online (Sandbox Code Playgroud)

(不,这不是与 NUL 连接,而是按照 POSIX 的要求在没有分隔符的情况下连接。一些paste实现也支持,paste -sd '' -但这既不是标准的也不是可移植的)。

请注意,除了在 busybox 实现中,如果输入为空,它会生成一个空行作为输出(不幸的是,现在 POSIX 规范中刻有历史错误/错误特征)。

使用 POSIX sed

sed -e :a -e '$!{N;ba' -e '}' -e 's/\n//g'
Run Code Online (Sandbox Code Playgroud)

或者:

sed '
:a
$!{
  N
  ba
}
s/\n//g'
Run Code Online (Sandbox Code Playgroud)

b:}命令不能跟其他的命令。在 POSIX 规范的早期版本中,b a;s/a/b/需要b分支到名为 的标签a;s/a/b/,在规范的较新版本中,它现在未指定,以允许 GNUsed行为。以下命令必须在后续表达式中或在单独的行中。

POSIX 还要求N在最后一行退出而不打印模式空间。GNUsed仅在 POSIX 模式下执行此操作,例如当POSIXLY_CORRECT环境中存在变量或您的--posix选项时,这解释了为什么使用--posix.

另请注意,POSIX 保证的模式空间的最小大小为 8192 字节。您只能将这种方法可移植地用于非常小的文件。paste没有大小限制,与该sed方法相反,不需要在打印之前将整个文件加载到内存中。

另一种方法是tr -d '\n'。但是请注意,与paste/相反sed,它会在输出上生成一个非分隔行(输出abc而不是abc\n上面的示例)。

在任何情况下,<<<是一个zsh操作符(现在被其他一些 shell 支持),$'...'是一个 ksh93 操作符(现在被大多数其他类似 POSIX 的 shell 支持),也不是 POSIXsh操作符(尽管后者可能会被添加到下一个标准的主要修订版),因此不应在 POSIXsh脚本中使用。