协慌网

登录 贡献 社区

如何使用 sed 替换换行符(\ n)?

如何使用 sed 命令替换换行符( \n )?

我没试成功:

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

我如何解决它?

答案

tr代替?

tr '\n' ' ' < input_filename

或完全删除换行符:

tr -d '\n' < input.txt > output.txt

或者如果你有 GNU 版本(有很长的选项)

tr --delete '\n' < input.txt > output.txt

在 GNU sed使用此解决方案:

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

这将在循环中读取整个文件,然后用空格替换换行符。

说明:

  1. 通过:a创建标签:a
  2. 通过N将当前和下一行附加到模式空间。
  3. 如果我们在最后一行之前,则跳转到创建的标签$!ba$!表示不在最后一行上执行,因为应该有一个最终换行符)。
  4. 最后,替换用模式空间(即整个文件)上的空格替换每个换行符。

这是与 BSD 和 OS X 的sed一起使用的跨平台兼容语法(根据@Benjie 评论 ):

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

正如您所看到的,使用sed来解决这个简单的问题是有问题的。有关更简单和适当的解决方案,请参阅此答案

快速回答:

sed ':a;N;$!ba;s/\n/ /g' file
  1. 创建标签'a'
  2. N 将下一行附加到模式空间
  3. $! 如果不是最后一行ba 分支(转到)标签'a'
  4. s 替换/ \ n / 正则表达式为新行// 由空格/ g 全局匹配(尽可能多次)

sed 将遍历步骤 1 到 3,直到它到达最后一行,让所有行都适合模式空间,其中 sed 将替换所有 \ n 字符


替代方案

sed不同,所有替代方案都不需要到达最后一行来开始该过程

bash ,慢

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

perlsed- like 速度

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

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

tr '\n' ' ' < file

粘贴tr般的速度,只能替换一个字符

paste -s -d ' ' file

awktr- like 速度

awk 1 ORS=' ' file

其他替代方法如“echo $(很慢,仅适用于小文件,需要处理整个文件才能开始进程。


来自sed FAQ 5.10 的 长篇答案

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

\ n 将永远不会匹配行尾的换行符,因为
在将线放入线之前,新线始终被剥离
模式空间。要在模式空间中获得 2 行或更多行,请使用
'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' 实用程序在这里是首选。
如果文件的最后一行包含换行符,GNU sed 将添加
输出的换行但删除所有其他,而 tr 将
删除所有换行符。

要匹配两行或更多行的块,有 3 种基本选择:
(1)使用'N' 命令将 Next 行添加到模式空间;
(2)使用'H' 命令至少两次追加当前行
到保留空间,然后从保留空间检索行
用 x,g 或 G; 或(3)使用地址范围(见上文第 3.3 节)
匹配两个指定地址之间的行。

选择(1)和(2)将 \ n 放入模式空间,在那里
可以根据需要进行寻址('s / ABC \ nXYZ / alphabet / 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,

除了传统的 '/ from here /,/ to there / {...}' 范围
地址,可以完全避免使用 \ n。