使用 POSIX sed 连接行

使用 POSIX sed 连接行

我正在尝试使用 POSIX sed 连接行。

使用 GNU sed(不带 --posix),可以按预期工作:

$ sed ':a; N; s/\n//; b a' <<< $'a\nb\nc'
abc

但如果我使用 --posix 我不会得到任何输出。

这是为什么?否则我该怎么办?

答案1

这是一份工作paste

printf '%s\n' a b c | paste -sd '\0' -

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

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

使用 POSIX sed

sed -e :a -e '$!{N;ba' -e '}' -e 's/\n//g'

或者:

sed '
:a
$!{
  N
  ba
}
s/\n//g'

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

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

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

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

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

答案2

对于每个 UNIX 机器上的任何 shell 中的任何 awk,对于任何大小的输入文件(除非该输入文件只是一大行文本,不包含无法放入内存的空格):

$ printf '%s\n' a b c | awk -v ORS= '1; END{if (NR) print RS}'
abc

相关内容