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

如何使用sed替换换行符(\n)?,sed,Sed,如何使用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' <

如何使用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
该版本按照您预期的方式工作

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

正如评论中所指出的,值得注意的是,这项修订已经到位-i、 bak将在替换之前为您提供原始文件的备份,以防您的文件没有您想象的那么聪明。

我不是专家,但我想在sed中,您首先需要将下一行附加到模式空间中,bij使用Dale Dougherty和Arnold Robbins一书中高级sed命令中的截面多行模式空间中的N;奥雷利1997;第107页,共页:

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

来自man sed:

[2addr]N

将下一行输入追加到模式空间,使用嵌入的换行符将追加的内容与原始内容分开。请注意,当前行号会更改


我必须搜索多个格式不正确的日志文件,其中的搜索字符串可能位于孤立的下一行。

将此解决方案与GNU sed结合使用:

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

说明:

通过:a创建标签。 通过N将当前行和下一行追加到模式空间。 如果我们在最后一行之前,分支到创建的标签$!ba$!意思是不要在最后一行做,因为应该有最后一行换行。 最后,替换用模式空间上的一个空间(即整个文件)替换每个换行符。 以下是适用于BSD和OS X的sed的跨平台兼容语法,如下所示:


如您所见,将sed用于这个简单的问题是有问题的。有关更简单和适当的解决方案,请参见。

带有以下内容的答案:标签

。。。在freebsd 7.2的命令行中不起作用:

( echo foo ; echo bar ) | sed ':a;N;$!ba;s/\n/ /g' sed: 1: ":a;N;$!ba;s/\n/ /g": unused label 'a;N;$!ba;s/\n/ /g' foo bar 但是如果您将sed脚本放在文件中或使用-e构建sed脚本

> (echo foo; echo bar) | sed -e :a -e N -e '$!ba' -e 's/\n/ /g' foo bar 或者

> cat > x.sed << eof
:a
N
$!ba
s/\n/ /g
eof

> (echo foo; echo bar) | sed -f x.sed
foo bar

可能OS X中的sed与之类似。

在使用FreeBSD sed的Mac OS X上:

# replace each newline with a space
printf "a\nb\nc\nd\ne\nf" | sed -E -e :a -e '$!N; s/\n/ /g; ta'
printf "a\nb\nc\nd\ne\nf" | sed -E -e :a -e '$!N; s/\n/ /g' -e ta
谁需要sed?下面是bash的方式:


针对上述tr解决方案,在可能使用Gnuwin32版本tr的Windows上,建议的解决方案:

tr '\n' ' ' < input
不适用于我,它可能会出错,或者由于某种原因实际替换了

使用tr的另一个功能,删除选项-d确实有效:

tr -d '\n' < input
或者用“\r\n”代替“\n”

三件事

绝对不需要tr或cat等。GNU sed和GNU awk结合起来,可以完成99.9%的文本处理

小溪!=基于行的。ed是一个基于行的编辑器。塞德不是。有关差异的更多信息,请参阅。大多数人把sed误认为是基于行的,因为默认情况下,它对简单匹配的模式匹配不是很贪婪——例如,当执行模式搜索并替换为一个或两个字符时,默认情况下它只替换找到的第一个匹配,除非global命令另有规定。如果全局命令是基于行而不是基于流的,则甚至不会有全局命令,因为它一次只计算行。试着跑跑步;你会注意到区别。如果您想在特定的行(如for循环)上进行迭代,ed非常有用,但大多数情况下您只需要sed

尽管如此

sed -e '{:q;N;s/\n/ /g;t q}' file
在GNU sed版本4.2.1中运行良好。上述命令将用空格替换所有换行符。它很难看,而且输入有点麻烦,但它工作得很好。{}可以省略,因为它们只是出于理智的原因才被包括在内

要删除空行,请执行以下操作:

sed -n "s/^$//;t;p;"
使用Awk:

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

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

$ (echo foo; echo bar) | sed -n 'H;${x;s/\n//g;p;}'
foobar
然而,有人告诉我,在某些sed实现中,保持空间可能是有限的。

快速回答 sed':a;N、 美元!文学士;s/\n//g'文件 :a创建标签“a” N将下一行追加到模式空间 $! 如果不是最后一行,ba分支机构转到标签“a” s将“//\n/regex”替换为新行,//替换为空格,/g 尽可能多地进行全局匹配 sed将循环执行步骤1到步骤3,直到到达最后一行,使所有行都适合模式空间,sed将替换所有\n字符

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

用bash,慢一点

读行时;不打印%s$行;完成<文件 使用perl,sed般的速度

perl-p-e的/\n/'文件 使用tr,比sed快,只能替换为一个字符

tr'\n'<文件 使用粘贴,tr般的速度,只能替换为一个字符

粘贴-s-d“”文件 用awk,tr一样的速度

awk 1 ORS=''文件 其他替代方法,如echo$ 答案很长 5.10。为什么不能使用转义符匹配或删除换行符 序列为什么不能使用匹配2行或多行\n

\n将永远不会匹配行末尾的换行符,因为 换行符总是在将换行符放入 模式空间。要将两行或更多行放入图案空间,请使用 “N”命令或类似命令,如“H;”;。。。;g、 "

Sed的工作原理是这样的:Sed一次读一行,切掉 终止换行符,将剩余的内容放入模式空间 sed脚本可以寻址或更改它,并且当模式空间 打印,将换行符附加到标准输出或文件。如果 使用“d”或“d”完全或部分删除模式空间,则 在这种情况下不添加换行符。因此,脚本

sed的/\n/'文件从每行中删除换行符 sed的/\n/foo\n/”文件在每行末尾添加一个单词 将永远不起作用,因为尾部换行符在 线条被放入图案空间。要执行上述任务, 请改用以下脚本之一:

tr-d'\n'<文件使用tr删除换行符 sed':a;N、 美元!文学士;s/\n//g'文件GNU用于删除换行符 sed的/$/foo/'文件将foo添加到每行的末尾 由于GNU sed以外的sed版本对 这里首选模式缓冲区、Unix“tr”实用程序。 如果文件的最后一行包含换行符,GNU sed将添加 将该换行符添加到输出,但删除所有其他换行符,而tr将 删除所有换行符

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

选项1和2将在模式空间中放置一个\n 可根据需要地址为“s/ABC\nXYZ/alphabet/g”。一个例子 第4.13节介绍了使用“N”删除一组行的方法 如何删除特定连续行的块?。这 可以通过将delete命令更改为其他命令来修改示例 否则,像“p”打印、“i”插入、“c”更改、“a”附加、, 或“s”替代品

选项3不会在模式空间中放置\n,但会 匹配一个连续的行块,因此可能不匹配 甚至需要\n来找到您要查找的内容。自从GNU使用 版本3.02.80现在支持以下语法:

sed'/start/,+4d'删除start加上接下来的4行, 除了传统的“/从这里/,/到那里/{…}”范围之外
地址,可以完全避免使用。

在某些情况下,您可以将RS更改为其他字符串或字符。这样,\n可用于sub/gsub:

$ gawk 'BEGIN {RS="dn" } {gsub("\n"," ") ;print $0 }' file
shell脚本的强大之处在于,如果您不知道如何以一种方式执行,那么您可以用另一种方式执行。很多时候,你需要考虑的事情比简单问题的复杂解决方案还要多

关于gawk很慢的事情。。。并将文件读入内存,我不知道这一点,但对我来说,gawk似乎每次只处理一行,速度非常非常快,不像其他一些行那么快,但编写和测试的时间也很重要

我处理MB甚至GB的数据,我发现唯一的限制是行大小。

易于理解的解决方案 我有这个问题。关键是我需要解决方案来处理BSD的MacOSX和GNU的Linux、sed和tr:

输出:

foo
bar
baz
有尾随的换行符

它可以在Linux、OS X和BSD上工作——即使没有支持或使用蹩脚的终端

使用tr将换行符与其他字符交换

NULL\000或\x00很好,因为它不需要UTF-8支持,也不太可能被使用

使用sed匹配空值

如果需要,可以使用tr调回额外的换行符


我使用了一种混合方法,通过使用tr将新行替换为ta来绕过新行 B,然后用我想要的替换标签。在本例中,因为我试图生成HTML中断

echo -e "a\nb\nc\n" |tr '\n' '\t' | sed 's/\t/ <br> /g'`

为了使用awk将所有换行符替换为空格,而不将整个文件读入内存:

awk '{printf "%s ", $0}' inputfile
如果您想要最终换行:

awk '{printf "%s ", $0} END {printf "\n"}' inputfile
您可以使用空格以外的字符:

awk '{printf "%s|", $0} END {printf "\n"}' inputfile

较短的awk备选方案:

awk 1 ORS=' '
解释 awk程序由规则组成,规则由条件代码块组成,即:

condition { code-block }
如果省略代码块,则使用默认值:{print$0}。因此,1被解释为真实条件,并且对每一行执行打印$0

当awk读取输入时,它会根据RS Record Separator的值将其拆分为记录,默认情况下,RS Record Separator是一个换行符,因此awk将在默认情况下按行解析输入。拆分还涉及从输入记录中剥离R

现在,当打印一条记录时,ORS输出记录分隔符被附加到记录上,默认值也是换行符。因此,通过将OR更改为空格,所有换行符都将更改为空格。

用任何字符串替换换行符,并替换最后一个换行符 纯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>
您可以使用xargs-默认情况下,它将\n替换为一个空格

但是,如果您的输入包含任何未终止的报价,例如,如果给定行上的报价符号不匹配,则会出现问题

tr '\n' ' ' 
这是命令

简单易用。

是sed在正常替换后引入新线的。首先,它修剪新行字符,然后根据您的指令进行处理,然后引入新行

使用sed,您可以为每个输入行使用您选择的字符串替换行尾,而不是修剪后的新行字符;但是,sed将输出不同的行。例如,假设您想用===替换行尾,而不是用单个空格替换:

PROMPT~$ cat <<EOF |sed 's/$/===/g'
first line
second line
3rd line
EOF

first line===
second line===
3rd line===
PROMPT~$
要用字符串替换新行字符,您可以像前面指出的那样,使用tr将新行字符替换为一个特殊字符,然后使用sed将该特殊字符替换为您想要的字符串

例如:

PROMPT~$ cat <<EOF | tr '\n' $'\x01'|sed -e 's/\x01/===/g'
first line
second line
3rd line
EOF

first line===second line===3rd line===PROMPT~$
防弹解决方案。二进制数据安全且兼容POSIX,但速度较慢。 需要根据 和 定义,因此不允许空字节和太长的行,并且每行必须以换行结束,包括最后一行。这使得使用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参考文档: , , , , , , ,

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

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

您可以使用:


您也可以使用此方法:

sed 'x;G;1!h;s/\n/ /g;$!d'
解释 流 当第一行从输入中获取时,进行交换,因此1转到保留空间,\n转到模式空间,将保留空间追加到模式空间,然后执行替换并删除模式空间

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

GNU sed有一个选项,-z,用于空分隔记录rds线路。您只需拨打:

sed -z 's/\n/ /g'
另一个GNU-sed方法,几乎与相同,但它使用了sed使用频率较低的y音译命令,该命令保存了尾随g的一个字节代码:

人们可能希望y的运行速度比s快,也许是tr速度的20倍,但在GNU sed v4.2.2中,y比s慢约4%

更便携的BSD sed版本:


使用“允许”查找和替换\n

sed -ie -z 's/Marker\n/# Marker Comment\nMarker\n/g' myfile.txt
标记

变成

标记注释

标记


如果您不幸不得不处理Windows行结尾,则需要删除\r和\n:


为什么我没有用awk找到一个简单的解决方案

如果要用空格或其他空格分隔原始行,printf将打印不带换行符的每一行:

awk '{printf $0 " "}' file

我不明白为什么sed不能这样做。请澄清使用不同的工具。sed是基于线的,因此它是

亚历山大:流编辑器的意思是基于行的吗?sed在输入流上工作,但它以换行符分隔的块来理解它。它是一个unix工具,这意味着它可以很好地完成一件事。一件事是在文件行上工作。让它做其他的事情将是困难的,而且有可能会有问题。这个故事的寓意是:选择正确的工具。你提出的很多问题似乎都是这样的:我如何才能让这个工具做一些本来不该做的事情?这些问题很有趣,但如果它们是在解决实际问题的过程中出现的,那么你可能是做错了。sed不是不言自明的,但如何仅在特定位置替换行尾?请至少提及-没有后缀的i不作备份-i、 bak可以防止你犯一个简单而难看的错误,比如忘记键入-p并将文件归零。@Telemachus:这是一个公平的观点,但可以用任何一种方式来论证。我没有提到它的主要原因是OP问题中的sed示例没有进行备份,因此在这里似乎是多余的。另一个原因是我从来没有真正使用过备份功能,我觉得自动备份很烦人,所以我总是忘记它在那里。第三个原因是它使我的命令行长了四个字符。不管是好是坏,也许更糟,我是一个强迫性的极简主义者;我只是喜欢简洁。我知道你不同意。我会尽我最大的努力记住在将来对备份发出警告。@Ire_和_诅咒:事实上,你刚才为忽略我做了一个非常好的理由。也就是说,你们的选择是有理由的,无论我是否同意这些选择,我当然尊重这一点。我不完全知道为什么,但最近我一直为这个特殊的事情而激动不已,Perl中没有后缀的-I标志。我相信我很快就会找到其他让我着迷的东西非常不幸的是,通过指定-for文件名,stdin无法实现这一点。有办法吗?这是我不用担心修改文件的方法,它使用以cat开头的管道。@StevenLu Perl默认情况下,如果没有提供文件名,将从STDIN读取。因此,您可以执行例如perl-i-p-e的/\n/'outfileUpvote,我通常使用最上面的答案,但是当管道/dev/uradom通过它时,sed在EOF之前不会打印,^C不是EOF。此解决方案每次看到换行时都会打印。正是我需要的!谢谢那么为什么不呢:echo-n`cat days.txt`@Tony,因为backticks已被弃用,而cat是多余的;-使用:echo$,读取行时不使用cat:while;do echo-n$行;完成output.txt这在Windows 10上使用Gnuwin32:cat SourceFile.txt | tr-delete'\r\n'>OutputFile.txt工作。或者,代替Gnuwin32,在Windows上使用GOWGNU,一系列-e参数在使用MKS的Windows上对我有效!谢谢您可以通过单独执行命令而不是使用分号sed-e':a'-e'N'-e'$在Mac OS X上跨平台运行此命令!ba'-e's/\n//g'似乎没有删除最后一个\n?请参见上面的数字3。看来是美元!意思是不要在最后一行做,因为应该有最后一行。这是一个令人印象深刻的答案。我还发现讽刺的是,Linux工具应该做一件事,而大多数Linux工具似乎做了很多事情,poorlyecho Hello\nWorld | sed-e':a'-e'N'-e'$!ba'-e's/\n//g'返回Hello World,但回显Hello World | sed-e':a'-e'n'-e'$!ba'-e's/\n//g'为我返回一个空字符串。我在大苏尔MacOS。如果你把外部的引号改成单引号,你不需要避开引号和美元符号。字母o通常被认为是变量名的错误选择,因为它可能与数字0混淆。您也不需要初始化变量,它默认为空字符串。但是,如果您不需要额外的前导空格:awk'{s=s sp$0;sp=}END{print s}'。但是,请参阅我的答案,了解如何在不将整个文件读入内存的情况下使用awk。请改为签出。与此方法相比,它更高效、可读性更好,尽管它可以工作!伙计,我明白了。无需在我脸上摩擦:-托尔的答案在页面上方,不管怎样,这是正确的,那么你关心什么?tr是一个好主意,你的全面报道是一个高质量的答案。+1用于使用粘贴。。。还有所有其他人@elgalu试试这个答案最好的部分是,长答案准确地解释了命令的工作方式和原因。这可能是我在stackexchange上读到的数千个答案中最有帮助的一个。我需要跨行匹配多个字符。以前的sed示例没有涉及多行,tr无法处理

e多字符匹配。Perl看起来不错,但没有像我预期的那样工作。如果可以的话,我会对这个答案投上几次赞成票。这是不好的,因为它会在输入中包含@@StevenLu:No,@的任何输入上产生不需要的输出。它被转义到%a并再次返回。该解决方案可能不完全符合POSIX,尽管不允许空字节,因此不适合二进制数据,并且所有行都必须以换行结束,因此tr输出不是真正有效的。啊。我看你已经修好了。对于应该是一个简单的操作来说有点复杂,但是很好的工作。我非常喜欢这个简单的解决方案,它比其他解决方案更可读,如果它更有意义,它可以有效地写为:awk'BEGIN{ORS=}{print$0}END{print\n}file.txt添加一个结尾换行符来说明BEGIN/END;1的计算结果为true。处理该行并打印该行。还可以将条件添加到此表达式中,例如,仅处理与模式匹配的行:awk'BEGIN{ORS=}/pattern/{print$0}END{print\n}您可以执行更简单的操作:code awk'ORS='file.txt code这样使用awk时,不幸的是,文件中的最后一行提要也被删除。请参阅上面Patrick Dark关于在类似于“cat file | echo$tr\012”的子shell中使用“tr”的回答,这会起到作用。漂亮。@Jonah:这是设置变量的另一种方式,比如说,作为一个只知道足够的sed来做基本事情的人,我不得不说,这不仅仅是关于你能用sed做什么,而是关于理解发生了什么有多容易。我很难使用sed,因此如果我能使用它,我更希望使用一个更简单的命令。使用tq作为条件跳转,这可以使用像s/\n//这样的模式来连接所有以空格开头的行,而无需将整个文件读入内存。转换多兆字节文件时非常方便。您链接的文章没有反映您所说的内容。这比大输入的公认答案慢近800倍。这是因为在越来越大的输入上运行“替换每一行”。或者,如果不想添加空格,只需tr-d'\n',但是,请注意echo“Y”| sed“x;G1.Hs/\n/X/g;$!d'结果为XY。这是用于GNU Sed的。在正常Sed中,这将给出Sed:1:s/^$/;Tp、 :未定义标签';p、 "。xargs还可以很好地处理最后一行:如果用单个字符替换单个字符,tr是唯一适合该作业的工具,而上面的示例显示了用空格替换换行符。。所以在上面的例子中,tr可以工作。。但是稍后会限制.tr在正确工具中的应用,因为提问者希望用空格替换每条换行符,如他的示例所示。换行符的替换对于sed来说是唯一的神秘,但是tr很容易完成。这是一个常见的问题。执行regex替换不是由tr完成的,而是由sed完成的,sed将是正确的工具。。。对于不同的问题,tr也可以删除换行符'tr-d'\n',但是您可能还希望删除更通用的返回值'tr-d'\012\015'`。警告:对于Linux和旧版Solaris机器(如sol5.8)之间的字符范围,tr的作用不同。例如:`tr-d'a-z`和`tr-d'[a-z]`。为此,我建议您使用sed,它没有任何区别。@MikeS谢谢您的回答。用回音跟随tr“\012”。否则,文件中的最后一个换行符也将被删除。tr'\012'<文件名;EchoDo做到了。即使输入包含空值,它们也将作为记录分隔符保留。如果没有空值,这不会加载整个输入吗?在这种情况下,处理一个千兆字节的文件可能会很麻烦。@Ruslan,是的,它会加载整个输入。这种解决方案对于千兆字节的文件来说不是一个好主意。这确实是最好的答案。其他的表情太扭曲了,记不起来了@JJoao你可以使用-u,-无缓冲。man mage声明:从输入文件加载最少的数据,并更频繁地刷新输出缓冲区。@Ruslan如果您有一个数千GB的文本文件,您无论如何也不想使用sed,即使是在基于行的模式下,因为sed在大输入时速度慢得令人讨厌。术语中有一点微妙:字符\000通常被称为NUL one L,在C/C++中,当谈论零指针时,通常使用NULL。答案中用空字符串替换隐藏了一个事实,即始终使用H附加到保留空间意味着保留空间将以换行开始。为了避免这种情况,您需要使用1h;2,$H$使用BSD sed y的{x;s/\n/x/g;p}快约15%。请参阅以获取一个工作示例。另外,对于BSD,sed命令需要在标签后终止,因此sed-e':a'-e'N;$!ba'-e'y/\n//'将是一个不错的选择。对我来说:xargstr不存在的TEM?它们现在似乎无处不在,但我想我还记得它们不适用于HP-UX、AIX和Irix等恐龙的系统?echo 1\n2\n3 | awk'{printf$0},这对我来说很有用@EDI9999这是在git bash for windows中唯一对我有效的方法
seq 10 | xargs
seq 10 | xargs echo -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.
sed -z 's/\n/ /g'
sed ':a;N;$!ba;y/\n/ /'
sed -e ':a' -e 'N;$!ba' -e 'y/\n/ /'
sed -ie -z 's/Marker\n/# Marker Comment\nMarker\n/g' myfile.txt
tr '\r\n' ' ' < $input > $output
awk '{printf $0}' file
awk '{printf $0 " "}' file