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

我尝试过:

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

如何修复?


当前回答

tr '\n' ' ' 

是命令。

简单易用。

其他回答

快速回答

sed ':a;N;$!ba;s/\n/ /g' file

:a创建标签“a”N将下一行附加到模式空间$! 如果不是最后一行,ba分支(转到)标记为“a”s替换,/\n/regex替换新行,//替换空格,/g全局匹配(尽可能多次)

sed将循环执行步骤1到3,直到到达最后一行,使所有行都符合模式空间,sed将替换所有字符


选择

与sed不同的是,所有备选方案都不需要到达最后一行即可开始流程

用bash,慢

while read line; do printf "%s" "$line "; done < file

使用perl,sed般的速度

perl -p -e 's/\n/ /' file

使用tr,比sed更快,只能替换为一个字符

tr '\n' ' ' < file

与粘贴类似,tr速度,只能替换为一个字符

paste -s -d ' ' file

具有awk,tr般的速度

awk 1 ORS=' ' file

其他替代方法如“echo$(<file)”速度较慢,仅适用于小文件,需要处理整个文件才能开始处理。


sed常见问题解答5.10的长答案

5.10.为什么不能使用转义符匹配或删除换行符序列为什么我不能使用\n匹配2行或更多行?

\n永远不会匹配行尾的换行符,因为在将换行符放入图案空间。要在图案空间中获得两条或多条线,请使用“N”命令或类似命令(如“H;…;g;”)。

Sed是这样工作的:Sed每次读取一行终止换行符,将剩余内容放入模式空间,其中sed脚本可以寻址或更改它,并且当模式空间打印时,将换行符附加到stdout(或文件)。如果用“d”或“d”完全或部分删除图案空间在这种情况下不添加换行符。因此,脚本如

  sed 's/\n//' file       # to delete newlines from each line             
  sed 's/\n/foo\n/' file  # to add a word to the end of each line         

将永远不会工作,因为尾随换行符在将线放入图案空间。为了执行上述任务,请改用以下脚本之一:

  tr -d '\n' < file              # use tr to delete newlines              
  sed ':a;N;$!ba;s/\n//g' file   # GNU sed to delete newlines             
  sed 's/$/ foo/' file           # add "foo" to end of each line          

由于除了GNU sed之外的sed版本对模式缓冲区,Unix“tr”实用程序在这里是首选的。如果文件的最后一行包含换行符,GNUsed将添加输出的新行,但删除所有其他行,而tr将删除所有换行符。

要匹配包含两行或更多行的块,有三种基本选择:(1) 使用“N”命令将“下一行”添加到图案空间;(2) 至少使用两次“H”命令附加当前行到保留空间,然后从保留空间检索行x、g或g;或(3)使用地址范围(见上文第3.3节)以匹配两个指定地址之间的行。

选项(1)和(2)将\n放入模式空间可以根据需要寻址('s/ABC\nXYZ/字母表/g')。一个例子使用“N”删除行块的方法见第4.13节(“如何删除特定连续行的块?”)。这可以通过将delete命令更改为其他命令来修改示例否则,如“p”(打印)、“i”(插入)、“c”(更改)、“a”(追加)、,或“s”(替代)。

选项(3)不会将一个\n放入模式空间,但它会匹配一块连续的行,因此可能不匹配甚至需要\n来查找所需内容。自GNU sed以来3.02.80版现在支持以下语法:

  sed '/start/,+4d'  # to delete "start" plus the next 4 lines,           

除了传统的“/从这里/,/到那里/{…}”范围地址,则可能完全避免使用。

我特别喜欢的解决方案是在保留空间中追加所有文件,并替换文件末尾的所有换行符:

$ (echo foo; echo bar) | sed -n 'H;${x;s/\n//g;p;}'
foobar

然而,有人告诉我,在一些sed实现中,保持空间可能是有限的。

tr '\n' ' ' 

是命令。

简单易用。

也可以使用此方法:

sed 'x;G;1!h;s/\n/ /g;$!d'

解释

x   - which is used to exchange the data from both space (pattern and hold).
G   - which is used to append the data from hold space to pattern space.
h   - which is used to copy the pattern space to hold space.
1!h - During first line won't copy pattern space to hold space due to \n is
      available in pattern space.
$!d - Clear the pattern space every time before getting the next line until the
      the last line.

Flow

当第一行从输入中获取时,进行交换,因此1进入保留空间,\n进入模式空间,将保留空间附加到模式空间,执行替换并删除模式空间。

在第二行中,进行交换,2到保持空间,1到模式空间,G将保持空间附加到模式空间中,h将模式复制到其中,进行替换并删除。此操作将继续,直到达到EOF并打印确切结果。

将此解决方案与GNU sed一起使用:

sed ':a;N;$!ba;s/\n/ /g' file

这将在循环中读取整个文件(':a;N;$!ba),然后用空格(s/\N//g)替换换行符。如果需要,可以简单地附加其他替换。

说明:

sed首先将除换行外的第一行读取到模式空间中。通过:a创建标签。通过N将新行和下一行附加到图案空间。如果我们在最后一行之前,请分支到创建的标签$!ba($!表示不在最后一行执行此操作。这是避免再次执行N所必需的,如果没有更多输入,则会终止脚本!)。最后,替换用模式空间(即整个文件)上的空格替换每一个换行符。

以下是与BSD和OS X的sed兼容的跨平台语法(根据@Benjie评论):

sed -e ':a' -e 'N' -e '$!ba' -e 's/\n/ /g' file

正如您所看到的,使用sed解决这个简单的问题是有问题的。要获得更简单和充分的解决方案,请参阅以下答案。