我正在尝试使用 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