如何使用sed命令将换行符(“\n”)替换为空格(“”)?
我尝试过:
sed 's#\n# #g' file
sed 's#^$# #g' file
如何修复?
如何使用sed命令将换行符(“\n”)替换为空格(“”)?
我尝试过:
sed 's#\n# #g' file
sed 's#^$# #g' file
如何修复?
当前回答
我不是专家,但我想在sed中,您首先需要将下一行追加到模式空间中,bij使用“N”。摘自《sed&awk》(Dale Dougherty and Arnold Robbins;O'Reilly 1997;预览版第107页)一书“高级sed命令”中的“多行模式空间”一节:
多行Next(N)命令通过读取新的输入行并将其附加到阵列空间的内容来创建多行阵列空间。模式空间的原始内容和新的输入行由换行分隔。嵌入的换行符可以通过转义序列“\n”进行模式匹配。在多行模式空间中,元字符“^”匹配模式空间的第一个字符,而不是任何嵌入换行符后面的字符。类似地,“$”只匹配模式空间中的最后一个换行符,而不匹配任何嵌入的换行符。执行Next命令后,控制权将传递给脚本中的后续命令。
发件人:
[2地址]N将下一行输入附加到模式空间,使用嵌入的换行符将附加的材料与原始内容分开。请注意,当前行号已更改。
我用它搜索了(多个)格式不正确的日志文件,其中搜索字符串可以在“孤立”的下一行找到。
其他回答
较短的锥子替代品:
awk 1 ORS=' '
解释
awk程序由由条件代码块组成的规则组成,即:
condition { code-block }
如果省略了代码块,则使用默认值:{print$0}。因此,1被解释为真条件,并且每行执行打印$0。
当awk读取输入时,它会根据RS(记录分隔符)的值将其拆分为记录,默认情况下是一个换行符,因此awk默认情况下将按行解析输入。拆分还涉及从输入记录中剥离RS。
现在,当打印记录时,ORS(输出记录分隔符)被附加到记录上,默认值也是一个换行符。因此,通过将ORS更改为空格,所有换行符都将更改为空格。
我不是专家,但我想在sed中,您首先需要将下一行追加到模式空间中,bij使用“N”。摘自《sed&awk》(Dale Dougherty and Arnold Robbins;O'Reilly 1997;预览版第107页)一书“高级sed命令”中的“多行模式空间”一节:
多行Next(N)命令通过读取新的输入行并将其附加到阵列空间的内容来创建多行阵列空间。模式空间的原始内容和新的输入行由换行分隔。嵌入的换行符可以通过转义序列“\n”进行模式匹配。在多行模式空间中,元字符“^”匹配模式空间的第一个字符,而不是任何嵌入换行符后面的字符。类似地,“$”只匹配模式空间中的最后一个换行符,而不匹配任何嵌入的换行符。执行Next命令后,控制权将传递给脚本中的后续命令。
发件人:
[2地址]N将下一行输入附加到模式空间,使用嵌入的换行符将附加的材料与原始内容分开。请注意,当前行号已更改。
我用它搜索了(多个)格式不正确的日志文件,其中搜索字符串可以在“孤立”的下一行找到。
将此解决方案与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解决这个简单的问题是有问题的。要获得更简单和充分的解决方案,请参阅以下答案。
为了使用awk将所有换行符替换为空格,而不将整个文件读入内存:
awk '{printf "%s ", $0}' inputfile
如果需要最后一行换行符:
awk '{printf "%s ", $0} END {printf "\n"}' inputfile
可以使用空格以外的字符:
awk '{printf "%s|", $0} END {printf "\n"}' inputfile
快速回答
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,
除了传统的“/从这里/,/到那里/{…}”范围地址,则可能完全避免使用。