如何使用sed
命令将换行符("\n
")替换为空格("")?
我尝试了以下命令但没有成功:
sed 's#\n# #g' file
sed 's#^$# #g' file
我该怎么修复它?
如何使用sed
命令将换行符("\n
")替换为空格("")?
我尝试了以下命令但没有成功:
sed 's#\n# #g' file
sed 's#^$# #g' file
我该怎么修复它?
sed
的设计初衷是用于基于行的输入。虽然它可以完成你需要的功能。
这里更好的选择是使用如下的tr
命令:
tr '\n' ' ' < input_filename
或者彻底删除换行符:
tr -d '\n' < input.txt > output.txt
或者如果你有 GNU 版本(带有其长选项)
tr --delete '\n' < input.txt > output.txt
tr
只能用于包含一个字符的字符串。你不能将所有换行符替换为一个多字符长的字符串。 - Flimm使用这个解决方案需要GNU sed
:
sed ':a;N;$!ba;s/\n/ /g' file
这将在循环中读取整个文件(':a;N;$!ba
'),然后用空格替换换行符('s/\n/ /g
')。如果需要,可以简单地追加其他替换。sed
从第一行开始读取,不包括换行符,将其放入模式空间。:a
' 创建一个标签。N
' 将一个换行符和下一行附加到模式空间中。$!ba
'('$!
' 表示不要在最后一行执行此操作。这是必需的,以避免再次执行 'N
',如果没有更多的输入,则会终止脚本!)。sed
兼容的跨平台语法(根据@Benjie comment):sed -e ':a' -e 'N' -e '$!ba' -e 's/\n/ /g' file
正如您所见,对于这个本来很简单的问题使用sed
是有问题的。查看这个答案以获取更简单、更适当的解决方案。
sed -e ':a' -e 'N' -e '$!ba' -e 's/\n/ /g'
- Benjieecho "Hello\nWorld" | sed -e ':a' -e 'N' -e '$!ba' -e 's/\n/ /g'
将返回 "Hello World"。但是,如果使用命令 echo "Hello World" | sed -e ':a' -e 'N' -e '$!ba' -e 's/\n/ /g'
,我会收到一个空字符串。我使用的操作系统是 MacOS Big Sur。 - Tobias Bergkvistsed ':a;N;$!ba;s/\n/ /g' file
sed会循环执行步骤1到3,直到达到最后一行,获取全部符合模式空间的内容,然后替换所有的\n字符
所有的替代方案,与sed不同,无需等到处理最后一行再开始处理
使用bash,速度较慢
while read line; do printf "%s" "$line "; done < file
使用Perl,具有类似于sed的速度
perl -p -e 's/\n/ /' file
使用 tr 比 sed 更快,能够只用一个字符替换内容。
tr '\n' ' ' < file
使用paste命令,类似于tr命令的速度,可以只用一个字符来替换。
paste -s -d ' ' file
使用 awk,类似于 tr 的速度
awk 1 ORS=' ' file
除了像"echo $(< file)"这样的另一种选择是慢,仅适用于小文件,并且需要处理整个文件才能开始进程。
5.10.为什么我不能使用 \n 转义序列来匹配或删除换行符?为什么我不能使用 \n 匹配两行或更多行?
\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'实用程序更好用。
如果文件的最后一行包含换行符,则GNU sed将将该换行符添加到输出中但删除所有其他换行符,而tr将删除所有换行符。
要匹配两行或更多行的块,有3种基本选择:
(1) 使用'N'命令将下一行添加到模式空间中;
(2) 至少使用两次'H'命令将当前行附加到Hold space中,然后使用x、g或G从hold space中检索行;或者 (3) 使用地址范围 (请参见上面的第3.3节) 匹配两个指定地址之间的行。
选择 (1) 和 (2) 将在模式空间中插入\n,从而可以按需要进行处理 ('s/ABC\nXYZ/alphabet/g')。在第4.13节 ("如何删除一个特定连续行的块?") 中出现了使用'N'删除一组行的示例。可以通过将删除命令更改为其他内容(例如'p'(打印),'i'(插入),'c'(更改),'a'(追加)或's'(替换))来修改此示例。
选择 (3) 不会将\n放入模式空间中,但它确实匹配连续行的块,因此您可能甚至不需要\n就可以找到要查找的内容。由于GNU sed版本3.02.80现在支持此语法:
sed '/start/,+4d' # to delete "start" plus the next 4 lines,
除了传统的'/从这里开始/到那里结束/{...}'范围地址之外,完全可以避免使用\n。
paste
,并使用其他所有工具,给出 +1。 - TotorGNU sed有一个选项-z
, 用于处理以null字符分隔的记录(行)。您可以直接调用:
sed -z 's/\n/ /g'
y
命令也可以完成这个工作 sed -z 'y/\n/ /' file
。 - potongawk 1 ORS=' '
一个 awk 程序由规则组成,这些规则包含条件代码块,即:
condition { code-block }
如果省略了代码块,则使用默认值:{ print $0 }
。 因此,1
被解释为真条件,print $0
将针对每行执行。awk
基于RS
(记录分隔符)将其拆分为记录,默认情况下为换行符,因此awk
将默认按行解析输入。 拆分还涉及从输入记录中剥离RS
。ORS
(输出记录分隔符),默认值再次为换行符。 因此,通过将ORS
更改为空格,所有换行符都将更改为空格。awk 'BEGIN { ORS=" " } { print $0 } END { print "\n" }' file.txt
(添加一个结束换行符只是为了说明开始/结束);数字“1”代表true
(处理该行),而print
(打印该行)。 这个表达式也可以添加条件,例如,只处理与模式匹配的行:awk 'BEGIN { ORS=" " } /pattern/ { print $0 } END { print "\n" }'
。 - michaelcode
awk 'ORS=" "' file.txt code
- Udi ORS=' '
?它是程序的一部分还是被解释为选项?我本以为你需要将其放在 BEGIN
块中或作为程序之前的选项,例如 awk -v ORS=' ' 1
。我无法确定 awk 如何解析 awk 1 ORS=' '
。 - Jonah-i
选项不会进行备份。使用-i.bak
可以避免一些容易犯的错误(例如忘记输入-p
选项而导致文件被清空)。 - Telemachus-i
会将内容写入文件。我之前从其他地方复制了一段代码,使用的是 source > destination
,但如果源文件和目标文件相同,那么目标文件会变成空白。因此,像这个答案中提到的 -i
可以帮助避免这种情况。非常感谢。 - vee-0777
标志,以便Perl一次性处理整个文件,即perl -0777 -i -p -e 's/\n//' file
。 - caw谁需要sed
?这里是bash
的方式:
cat test.txt | while read line; do echo -n "$line "; done
cat
命令,通过以下语句可以将 test.txt
中的每一行输出并以空格分隔:while read line; do echo -n "$line "; done < test.txt
。如果子 shell 是个问题,这可能会很有用。 - Carlo Cannasecho $(<file)
会将所有空格压缩成一个空格,不仅限于换行符:这超出了原帖的要求。 - glenn jackman为了使用awk将所有换行符替换为空格,而无需将整个文件读入内存:
awk '{printf "%s ", $0}' inputfile
如果你想要一个最后的换行符:awk '{printf "%s ", $0} END {printf "\n"}' inputfile
您可以使用除空格以外的字符:
awk '{printf "%s|", $0} END {printf "\n"}' inputfile
tr '\n' ' '
是该命令。
简单易用。
三件事。
tr
(or cat
, etc.) is absolutely not needed. (GNU) sed
and (GNU) awk
, when combined, can do 99.9% of any text processing you need.
stream != line based. ed
is a line-based editor. sed
is not. See sed lecture for more information on the difference. Most people confuse sed
to be line-based because it is, by default, not very greedy in its pattern matching for SIMPLE matches - for instance, when doing pattern searching and replacing by one or two characters, it by default only replaces on the first match it finds (unless specified otherwise by the global command). There would not even be a global command if it were line-based rather than STREAM-based, because it would evaluate only lines at a time. Try running ed
; you'll notice the difference. ed
is pretty useful if you want to iterate over specific lines (such as in a for-loop), but most of the times you'll just want sed
.
That being said,
sed -e '{:q;N;s/\n/ /g;t q}' file
works just fine in GNU sed
version 4.2.1. The above command will replace all newlines with spaces. It's ugly and a bit cumbersome to type in, but it works just fine. The {}
's can be left out, as they're only included for sanity reasons.
t q
作为条件跳转,可以在不读取整个文件到内存的情况下,适用于类似s/\n / /
模式(连接以空格开头的所有行)的操作。在转换多兆字节文件时非常方便。 - textshell
tr
命令是最适合的工具。但是上面的例子展示了将换行符替换为空格,因此在这种情况下,tr
命令可以使用。但是对于后续操作可能会有限制。 - Angry 84tr -d '\n'
,但您可能还想删除回车以使其更通用tr -d '\012\015'
。 - anthonytr -d 'a-z'
和tr -d '[a-z]'
。对此,我建议您使用没有这种区别的“sed”。 - anthonytr '\012' ' '
之后加上echo
。否则文件中的最后一个换行符也会被删除。使用tr '\012' ' ' < 文件名; echo
可以解决问题。 - Bernie Reiter