如何使用sed命令将换行符(“\n”)替换为空格(“”)?

我尝试过:

sed 's#\n# #g' file
sed 's#^$# #g' file

如何修复?


当前回答

三件事。

tr(或cat等)是绝对不需要的。(GNU)sed和(GNU)awk结合在一起,可以完成99.9%的文本处理。流!=基于行。ed是一个基于行的编辑器。sed不是。有关差异的更多信息,请参阅sed讲座。大多数人将sed误认为是基于行的,因为默认情况下,它对SIMPLE匹配的模式匹配并不十分贪婪-例如,当进行模式搜索并替换为一个或两个字符时,默认情况下它只替换找到的第一个匹配(除非全局命令另有规定)。如果它是基于行而不是基于STREAM的,甚至不会有全局命令,因为它一次只能计算行。尝试运行ed;你会注意到差异。如果您想要在特定行上迭代(例如在for循环中),ed非常有用,但大多数时候您只需要sed。尽管如此,sed-e“{:q;N;s/\N//g;t q}”文件在GNUsed版本4.2.1中运行良好。上述命令将用空格替换所有换行符。它很难看,输入起来有点麻烦,但它工作得很好。{}可以省略,因为它们只是出于理智的原因才被包括在内。

其他回答

cat file | xargs

为了完整起见

使用Awk:

awk "BEGIN { o=\"\" }  { o=o \" \" \$0 }  END { print o; }"

我不是专家,但我想在sed中,您首先需要将下一行追加到模式空间中,bij使用“N”。摘自《sed&awk》(Dale Dougherty and Arnold Robbins;O'Reilly 1997;预览版第107页)一书“高级sed命令”中的“多行模式空间”一节:

多行Next(N)命令通过读取新的输入行并将其附加到阵列空间的内容来创建多行阵列空间。模式空间的原始内容和新的输入行由换行分隔。嵌入的换行符可以通过转义序列“\n”进行模式匹配。在多行模式空间中,元字符“^”匹配模式空间的第一个字符,而不是任何嵌入换行符后面的字符。类似地,“$”只匹配模式空间中的最后一个换行符,而不匹配任何嵌入的换行符。执行Next命令后,控制权将传递给脚本中的后续命令。

发件人:

[2地址]N将下一行输入附加到模式空间,使用嵌入的换行符将附加的材料与原始内容分开。请注意,当前行号已更改。

我用它搜索了(多个)格式不正确的日志文件,其中搜索字符串可以在“孤立”的下一行找到。

防弹解决方案。二进制数据安全,符合POSIX,但速度较慢。

POSIX已使用需要根据POSIX文本文件和POSIX线定义,因此不允许NULL字节和过长的行,并且每行必须以换行符结尾(包括最后一行)。这使得使用sed处理任意输入数据变得困难。

下面的解决方案避免了sed,而是将输入的字节转换为八进制代码,然后再转换为字节,但拦截八进制代码012(换行)并输出替换字符串来代替它。据我所知,该解决方案符合POSIX,因此它应能在多种平台上工作。

od -A n -t o1 -v | tr ' \t' '\n\n' | grep . |
  while read x; do [ "0$x" -eq 012 ] && printf '<br>\n' || printf "\\$x"; done

POSIX参考文件:sh中,shell命令语言,od中,tr中,grep,阅读[,输出函数

read、[和printf都至少在bash中内置,但POSIX可能无法保证这一点,因此在某些平台上,每个输入字节可能会启动一个或多个新进程,这会降低速度。即使在bash,这种解决方案也只能达到50kB/s左右,因此不适合大型文件。

在Ubuntu(bash、dash和busybox)、FreeBSD和OpenBSD上测试。

用任何字符串替换换行符,并替换最后一个换行符

纯tr解决方案只能替换为单个字符,纯sed解决方案不能替换输入的最后一行。以下解决方案解决了这些问题,并且似乎对二进制数据是安全的(即使使用UTF-8语言环境):

printf '1\n2\n3\n' |
  sed 's/%/%p/g;s/@/%a/g' | tr '\n' @ | sed 's/@/<br>/g;s/%a/@/g;s/%p/%/g'

结果:

1<br>2<br>3<br>