\n
命令将换行符(“
”)替换为空格(“ sed
”)?我未成功尝试:
sed 's#\n# #g' file
sed 's#^$# #g' file
如何解决?
#1 楼
将此解决方案与GNUsed
配合使用:sed ':a;N;$!ba;s/\n/ /g' file
这将循环读取整个文件,然后用空格替换换行符。
< br解释:
通过
:a
创建标签。通过
N
将当前行和下一行添加到模式空间。如果我们在最后一行之前行,分支到已创建的标签
$!ba
($!
表示不要在最后一行执行此操作,因为应该有最后一个换行符。)最后,替换操作将每个换行符替换为模式空间上的空格(即整个空格)文件)。这是跨平台兼容的语法,可与BSD和OS X的
sed
(根据@Benjie注释)一起使用:sed -e ':a' -e 'N' -e '$!ba' -e 's/\n/ /g' file
如您所见,将
sed
用于这个否则简单的问题是有问题的。有关更简单和适当的解决方案,请参见以下答案。评论
您可以通过分别执行命令而不用分号分隔来运行此跨平台(即在Mac OS X上):sed -e':a'-e'N'-e'$!ba'-e's / \ n / / g'
–本杰
2011年9月27日上午11:16
似乎不删除最后一个\ n?
–皮埃尔·吉尔斯·勒瓦卢瓦
8月4日10:55
#2 楼
sed
打算用于基于行的输入。尽管它可以满足您的需要。这里更好的选择是使用
tr
命令,如下所示:tr '\n' ' ' < input_filename
或完全删除换行符:
tr -d '\n' < input.txt > output.txt
,或者如果您使用的是GNU版本(带有长选项)
tr --delete '\n' < input.txt > output.txt
评论
我不明白为什么sed无法做到这一点。请澄清使用其他工具。
–LéoLéopoldHertz준영
09年8月9日在19:18
Sed是基于行的,因此很难掌握换行符。
–亚历山大·格拉迪什(Alexander Gladysh)
09年8月9日在19:22
亚历山大:“流编辑器”是指基于行的吗?也许这个名字令人困惑。
–LéoLéopoldHertz준영
09年8月9日在19:26
sed可以处理“输入”流,但是可以用换行符分隔的块来理解它。这是一个Unix工具,这意味着它做得很好。一件事是“逐行处理文件”。使其执行其他操作将很困难,并且可能会出现越野车的风险。这个故事的寓意是:选择正确的工具。您的许多问题似乎都采用“我该如何使该工具执行从未打算做的事情?”的形式。这些问题很有趣,但是如果在解决一个实际问题的过程中出现这些问题,那么您可能做错了。
– dmckee ---前主持人小猫
09年8月9日在19:39
sed不是不言自明的,而是如何仅在特定位置替换行尾?
–user1767316
10月22日15:30
#3 楼
快速解答 sed ':a;N;$!ba;s/\n/ /g' file
:a创建标签'a'
N将下一行追加到模式空间
$!如果不是最后一行,则用ba分支(转到)标签'a'
替换,/ \ n /正则表达式换行,//空格,/ g全局匹配(尽可能多地)
sed将循环执行步骤1至3,直到到达最后一行,使所有行都适合sed将替换所有\ 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
具有awk和类似tr的速度
paste -s -d ' ' file
其他版本像“ echo $(<文件)”之类的词很慢,仅适用于小文件,需要处理整个文件才能开始执行该过程。
sed FAQ 5.10中的长答案
5.10。为什么我不能使用\ n转义
序列来匹配或删除换行符?为什么我不能使用\ n匹配两行或更多行?
\ n永远不会与行尾的换行符匹配,因为
换行符总是在插入行之前被剥离
模式空间。要将2行或更多行插入模式空间,请使用'N'命令或类似的命令(例如'H; ...; g;')。
sed的工作方式如下:sed读取一次仅一行,将
终止换行符删除,将剩下的内容放入模式空间中,其中
sed脚本可以对其进行寻址或更改,并且在打印模式空间
时,会在stdout(或文件)后添加换行符。如果
模式空间全部或部分被'd'或'D'删除,则在这种情况下不添加
换行符。因此,像
awk 1 ORS=' ' file
之类的脚本将永远无法工作,因为尾随的换行符是在将行放入行之前被删除的。模式空间。要执行上述任务,
请改用以下脚本之一:
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
由于sed版本不是GNU, 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 sed开始
版本3.02.80现在支持以下语法:除了传统的'/ from here /,/ to there / {...}'range
地址,有可能完全避免使用\ n。
评论
tr是一个好主意,您的总体覆盖范围可以为您提供最佳答案。
–新亚历山大
13年1月6日在17:57
+1使用(标准实用程序)粘贴...以及其他所有东西!
– Tortor
13年3月15日在11:10
@elgalu试试这个unix.stackexchange.com/questions/4527/…
– hdorio
2013年12月11日上午9:36
关于此答案的最好的部分是“长答案”准确地解释了命令的工作方式和原因。
–pdwalker
2014年5月2日,11:20
这可能是我在stackexchange上阅读的数千个答案中最有用的。我需要跨行匹配多个字符。以前的sed示例没有涵盖多行,tr无法处理多个字符匹配。 Perl看起来不错,但是没有按我预期的那样工作。如果可以的话,我会多次投票给这个答案。
–强大的力量
15年6月29日在23:37
#4 楼
一个较短的awk替代方法:awk 1 ORS=' '
解释
awk程序由规则组成,这些规则由条件代码块组成,即:
condition { code-block }
如果省略代码块,则使用默认值:
{ print 1
}
。因此,将print awk
解释为真实条件,并为每一行执行RS
。当
awk
读取输入时,它将根据RS
(记录分隔符)的值将其拆分为记录,默认情况下是换行符,因此默认情况下ORS
将逐行分析输入。拆分还涉及从输入记录中剥离ORS
。现在,在打印记录时,将q4312079q(输出记录分隔符)附加到记录中,默认情况下还是换行符。因此,通过将q4312079q更改为空格,所有换行符均更改为空格。
评论
我非常喜欢这个简单的解决方案,该解决方案比其他解决方案更具可读性
– Fedir RYKHTIK
13年7月30日在13:29
如果更有意义,则可以将其有效地写为:awk'BEGIN {ORS =“”} {打印$ 0} END {打印“ \ n”}'file.txt(添加结尾换行符只是为了说明开始/结束) ; “ 1”的计算结果为true(处理行)并打印(打印行)。也可以在此表达式中添加条件,例如,仅在与模式匹配的行上工作:awk'BEGIN {ORS =“”} / pattern / {print $ 0} END {print“ \ n”}'
–迈克尔
2014年9月19日在1:22
您可以更简单地做到这一点:code awk'ORS =“”'file.txt代码
– Udi
18 Mar 28 '18在15:52
不幸的是,当使用这样的awk时,文件中的最后一个换行符也会被删除。参见上面的Patrick Dark答案,关于在像`cat file | echo $ {tr“ \ 012”“”)`可以解决问题。好漂亮
–伯尼·瑞特(Bernie Reiter)
19年3月28日在11:54
#5 楼
gnu sed具有用于空分隔记录(行)的选项-z
。您可以致电:sed -z 's/\n/ /g'
评论
即使输入确实包含空值,也将保留它们(作为记录定界符)。
– Toby Speight
16年2月16日在17:42
如果没有空值,这不会加载整个输入吗?在这种情况下,处理数GB的文件可能会崩溃。
–俄罗斯
16 Mar 4 '16 at 9:43
@Ruslan,是的,它将加载整个输入。对于千兆字节的文件,此解决方案不是一个好主意。
– JJoao
16-3-4在9:50
认真地讲,这是最好的答案。其他表达方式太扭曲而无法记住。 @JJoao可以将它与-u,--unbuffered一起使用。管理人员指出:“从输入文件中加载最少的数据,并更频繁地刷新输出缓冲区”。
–not2qubit
18年2月21日在21:10
@Ruslan如果您有数GB的文本文件,则无论如何都不要使用sed,即使在基于行的模式下也是如此,因为sed烦人的大输入速度。
–vog
19年11月26日在23:19
#6 楼
Perl版本按照您期望的方式工作。perl -i -p -e 's/\n//' file
如注释中指出的那样,值得注意的是此编辑已就位。
-i.bak
将在替换前为您提供原始文件的备份,以防您的正则表达式不如您想象的那样聪明。评论
请至少提及-i不带后缀的文件不会进行备份。 -i.bak保护您免受一个简单的丑陋错误(例如,忘记键入-p并将文件清零)。
– Telemachus
09年8月9日在20:31
@Telemachus:这是一个公平的观点,但是无论哪种方式都可以争论。我没有提到它的主要原因是OP问题中的sed示例没有进行备份,因此在这里似乎是多余的。另一个原因是我从未真正使用过备份功能(实际上我发现自动备份很烦人),所以我总是忘记了它的存在。第三个原因是它使我的命令行延长了四个字符。不管是好是坏(可能更糟),我是一个强迫性的极简主义者。我只喜欢简洁。我知道您不同意。我会尽力记住以后要警告有关备份的问题。
–ire_and_curses
09年8月9日在20:53
@Ire_and_curses:实际上,您只是因为忽略我而提出了一个该死的好理由。也就是说,您有选择的理由,无论我是否同意选择,我都一定会尊重。我不确定为什么会这样,但是最近我一直对这个特殊的东西不满意(Perl中的-i标志没有后缀)。我相信我很快就会发现其他困扰的东西。 :)
– Telemachus
09年8月9日在21:36
真不幸的是,通过为文件名指定-,这不适用于stdin。有没有办法做到这一点?这是我不用担心修改文件的方法,它使用的是以cat开头的管道。
–陆even
19年4月10日在2:57
如果未提供文件名,则@StevenLu Perl将默认从STDIN读取。所以你可以做perl -i -p -e's / \ n //'
–ire_and_curses
19年4月10日在15:47
#7 楼
谁需要sed
?这是bash
的方式:cat test.txt | while read line; do echo -n "$line "; done
评论
Upvote,我通常使用最佳答案,但是当通过/ dev / urandom传递它时,sed直到EOF才打印,并且^ C并非EOF。每当看到换行符时,都会打印此解决方案。正是我需要的!谢谢!
–Vasiliy Sharapov
2011年2月9日在17:34
那为什么不呢:echo -n`cat days.txt`
–托尼
2012-09-26 23:51
@Tony,因为不推荐使用反引号,并且猫是多余的;-)使用:echo $(
–seumasmac
13年2月7日在16:03
甚至不使用cat:做echo -n“ $ line”;完成
–卡洛·卡纳斯(Carlo Cannas)
2014年1月20日17:42
echo $(
–格伦·杰克曼
15年3月18日在18:46
#8 楼
为了使用awk用空格替换所有换行符,而不将整个文件读入内存:awk '{printf "%s ", awk '{printf "%s ", awk '{printf "%s|", q4312078q} END {printf "\n"}' inputfile
} END {printf "\n"}' inputfile
}' inputfile
如果要最后一个换行符:
q4312078q
您可以使用空格以外的字符:
q4312078q
评论
END {print“”}是尾随换行符的较短替代。
–艾萨克
19/12/15在23:41
#9 楼
tr '\n' ' '
是命令。
简单易用。
评论
或者如果您不想添加空格,则直接使用tr -d'\ n'
– spudder
2014-10-15 23:26
#10 楼
三件事。绝对不需要
tr
(或cat
等)。 (GNU)sed
和(GNU)awk
结合使用时,可以完成您需要的任何文本处理的99.9%。stream!=基于行。
ed
是基于行的编辑器。 sed
不是。有关差异的更多信息,请参见sed讲座。大多数人将sed
混淆为基于行的,因为默认情况下,它对简单匹配的模式匹配不是很贪婪-例如,在进行模式搜索并替换一个或两个字符时,默认情况下它仅在第一个字符上替换找到的匹配项(除非全局命令另有指定)。如果是基于行而不是基于STREAM的话,甚至没有全局命令,因为它一次只能评估行。尝试运行ed
;您会注意到其中的区别。如果要遍历特定行(例如在for循环中),则ed
非常有用,但是在大多数情况下,您只需要sed
。这么说,
sed -e '{:q;N;s/\n/ /g;t q}' file
在GNU
sed
版本4.2.1中可以正常工作。上面的命令将所有换行符替换为空格。输入起来很丑陋而且有点麻烦,但是效果很好。可以省略{}
,因为出于理智的考虑而将它们包括在内。评论
作为一个仅了解sed足以做基本事情的人,我不得不说,这不仅仅是关于sed可以做什么的,而是要了解正在发生的事情有多么容易。我在使用sed时非常费力,因此在可以使用它时,我希望使用更简单的命令。
–内特
2014年4月4日19:15
使用t q作为条件跳转,可以使用s / \ n / /这样的模式(连接以空格开头的所有行),而无需将整个文件读入内存。转换数兆字节的文件时非常方便。
–textshell
15年6月26日在11:17
您链接的文章并不反映您的意思
– hek2mgl
16-3-29在22:33
这比接受大输入的答案慢了将近800倍。这是由于在越来越大的输入上可以替代每行。
–雷神
16年11月3日在20:17
#11 楼
易于理解的解决方案我遇到了这个问题。最重要的是,我需要解决方案才能在BSD(Mac OS X)和GNU(Linux和Cygwin)
sed
和tr
上工作:$ echo 'foo
bar
baz
foo2
bar2
baz2' \
| tr '\n' 'foo
bar
baz
0' \
| sed 's:\x00\x00.*:\n:g' \
| tr 'q4312078q0' '\n'
输出:
q4312078q
(具有换行符)
它可以在Linux,OS X和BSD上运行-即使不支持UTF-8或使用笨拙的终端。
使用
tr
可以将换行符与另一个字符交换。NULL
(\x00
0
或sed
)很不错,因为它不需要UTF- 8种支持,不太可能使用。如果需要,请使用
NULL
来匹配tr
使用q4312079q来换回多余的换行符
评论
关于术语的微妙注释:字符\ 000通常称为NUL(一个L),在谈论零指针时(在C / C ++中)通常使用NULL。
–sqweek
16-2-29在8:59
#12 楼
:a标签的答案...如何使用sed替换换行符(\ n)?
...在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相似。
评论
-e参数系列在使用MKS的Windows上对我有用!谢谢!
–JamesG
2011年9月7日在19:26
#13 楼
您可以使用xargs:seq 10 | xargs
或
seq 10 | xargs echo -n
评论
为我工作:xargs
– Udi
18年3月28日在16:31
#14 楼
为什么我找不到使用awk
的简单解决方案?其他:awk '{printf awk '{printf q4312078q " "}' file
}' file
评论
回声“ 1 \ n2 \ n3” | awk'{printf $ 0}',这对我有用。 @ edi9999
– Itachi
3月19日9:39
这是在git bash for Windows中对我有用的唯一方法
–柏拉图
5月15日0:00
#15 楼
我不是专家,但是我想在sed
中,您首先需要将下一行附加到模式空间中,使用“ N
” bij。从sed&awk的“高级sed命令”中的“多行模式空间”部分(Dale Dougherty和Arnold Robbins; O'Reilly 1997;预览的第107页)中:多行Next (N)命令通过读取输入的新行并将其附加到模式空间的内容来创建多行模式空间。模式空间的原始内容和新输入行由换行符分隔。嵌入的换行符可以通过转义序列“ \ n”在模式中进行匹配。在多行模式空间中,元字符“ ^”与模式空间的第一个字符匹配,而不与任何嵌入的换行符后面的字符匹配。同样,“ $”仅匹配模式空间中的最后一个换行符,而不匹配任何嵌入的换行符。执行Next命令后,控制权随后传递给脚本中的后续命令。
从
man sed
:[2addr] N
追加下一行输入到模式空间,使用嵌入的换行符将附加的材料与原始内容分开。请注意,当前行号发生了变化。
我已使用它来搜索(多个)格式错误的日志文件,其中搜索字符串可能在下一个“孤立”行中找到。 >
#16 楼
为了响应上面的“ tr”解决方案,在Windows上(可能使用的是Gnuwin32版本的tr),建议的解决方案是:tr '\n' ' ' < input
对我不起作用,它要么由于某种原因而出现错误,要么实际上替换了\ nw /。
使用tr的另一个功能,“-delete”选项-d确实可以工作:
tr -d '\n' < input
或'\ r \ n'代替'\ n'
评论
在Windows上,您可能需要使用tr“ \ n”“” <输入。 Windows Shell(cmd.exe)不会将撇号视为引号字符。
–基思·汤普森(Keith Thompson)
2011年8月24日14:25
否,在Windows 10 Ubuntu子系统中,您需要使用tr“ \ n \ r”“”
–user1491819
17-9-29于3:55
这在使用Gnuwin32的Windows 10上有效:cat SourceFile.txt | tr-删除'\ r \ n'> OutputFile.txt。或者,代替Gnuwin32,使用Gow(在Windows上为Gnu),github.com/bmatzelle/gow/wiki
–炼金术师
18年6月13日在23:15
#17 楼
我使用了一种混合方法来解决换行问题,方法是使用tr来用制表符替换换行符,然后用所需的选项卡来替换换行符。在这种情况下,为“”,因为我试图生成HTML中断。echo -e "a\nb\nc\n" |tr '\n' '\t' | sed 's/\t/ <br> /g'`
#18 楼
如果您不幸不得不处理Windows行尾,则需要删除\r
和\n
tr '\r\n' ' ' < $input > $output
评论
这将[替换为空格,\ r替换为空格,\ n替换为空格,]替换为空格。 tr -d'\ r \ n'<文件将删除任何\ r或\ n字符,但这也不是所要求的。 tr -d'\ r'<文件将删除任何\ r字符(无论它们是否与\ n相邻),这可能更有用,并且很可能满足OP的需要(仍然假设您的tr理解这一点)反斜杠符号)。
–tripleee
19/12/29在10:39
谢谢,修复它。只是不要输入[],tr确实尊重\ n和\ r作为新行并返回。有tr不存在的系统吗?
– StevenWernerCS
7月16日1:08
这些天,它们使无处不在的动物肥胖,但是我想我还记得它们不起作用的系统(也许像HP-UX和AIX以及Irix这样的恐龙?)
–tripleee
7月16日下午5:48
#19 楼
防弹解决方案。二进制数据安全且兼容POSIX,但速度较慢。POSIX sed
根据
POSIX文本文件
和
POSIX行要求输入
定义,因此不允许NULL字节和太长的行,并且每行必须以换行符结尾(包括最后一行)。这使得很难使用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参考文档:
sh ,
shell命令语言,
od,
tr,
grep,
[,
printf。
read
,[
和printf
都是至少以bash内置的,但是POSIX可能无法保证,因此在某些平台上,每个输入字节可能会启动一个或多个新进程,这会减慢速度事情下来。即使在bash中,该解决方案也只能达到约50 kB / s,因此它不适用于大文件。已在Ubuntu(bash,dash和busybox),FreeBSD和OpenBSD上进行了测试。
#20 楼
在某些情况下,您可以将RS
更改为其他字符串或字符。这样,\ n可用于sub / gsub:$ gawk 'BEGIN {RS="dn" } {gsub("\n"," ") ;print q4312078q }' file
Shell脚本的强大之处在于,如果您不知道如何以一种方式来执行它,则可以用另一种方式做。很多时候,与为一个简单的问题提供复杂的解决方案相比,您需要考虑的事情更多。
关于gawk速度很慢...并将文件读入内存的事情,我不知道这一点,但是对我来说gawk似乎可以处理一行,并且速度非常快(速度不如其他速度快,但是编写和测试的时间也很重要)。
我处理MB甚至GB的数据,而我发现的唯一限制是行大小。
#21 楼
查找并替换为使用\ nsed -ie -z 's/Marker\n/# Marker Comment\nMarker\n/g' myfile.txt
标记
成为
#标记注释
标记
#22 楼
您可以使用xargs
-默认情况下,它将用空格替换\n
。但是,如果您的输入中包含
unterminated quote
的任何情况,例如:如果给定行上的引号符号不匹配。评论
xargs还可以很好地处理最后一行:
–AAAfarmclub
15年8月22日在21:37
#23 楼
在Mac OS X上(使用FreeBSD sed):# 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
#24 楼
删除空行:sed -n "s/^$//;t;p;"
评论
这是针对GNU Sed的。在普通的Sed中,这会得到sed:1:“ s / ^ $ //; t; p;”:未定义标签'; p;'。
–LéoLéopoldHertz준영
15年6月8日在20:29
#25 楼
使用Awk:awk "BEGIN { o=\"\" } { o=o \" \" $0 } END { print o; }"
评论
如果将外部的单引号更改为引号和美元符号,则无需转义。字母“ o”通常被认为是变量名称的错误选择,因为它可能与数字“ 0”混淆。您也不需要初始化变量,它默认为空字符串。但是,如果您不想使用多余的前导空格:awk'{s = s sp $ 0; sp =“”} END {print s}'。但是,请参见我的答案以获取一种使用awk而不将整个文件读入内存的方法。
–已暂停,直至另行通知。
2012年3月30日在6:34
请改用Thor的答案。相对于此方法,它可以更有效,更易读且更胜一筹(即使这可行)!
–mschilli
2013年9月2日在17:03
杜德,我明白了。没必要在我的脸上擦拭它:-)无论如何,雷神的答案在页面上方(是正确的),那么您在乎什么呢?
– kralyk
2013年9月3日13:28
#26 楼
我特别喜欢的解决方案是将所有文件追加到保留空间中,并在文件末尾替换所有换行符:$ (echo foo; echo bar) | sed -n 'H;${x;s/\n//g;p;}'
foobar
但是,有人说我保留空间在某些sed实现中可以是有限的。
评论
在您的答案中用空字符串替换将掩盖一个事实,即始终使用H附加到保留空间意味着保留空间将以换行符开头。为避免这种情况,您需要使用1h; 2,$ H; $ {x; s / \ n / x / g; p}
–杰夫
16年7月9日在6:34
#27 楼
用任何字符串替换换行符,也替换最后一个换行符纯
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>
评论
这很糟糕,因为它将在包含@的任何输入上产生有害的输出
–陆even
2013年6月22日17:38
@StevenLu:不,@在输入中可以。它逃脱到%a,然后再次返回。但是,该解决方案可能并不完全符合POSIX(不允许使用NULL字节,因此对二进制数据不利,并且所有行都必须以换行符结尾,因此tr输出实际上不是有效的)。
–HåkonA. Hjortland
13年6月27日在0:48
啊。我看你已经解决了。 Kinda对于应该是简单的操作却是很好的工作感到费解。
–陆even
13-6-27在2:48
#28 楼
sed在“正常”替换之后引入换行符。首先,它会修剪换行符,然后根据您的说明进行处理,然后引入换行符。使用sed,您可以替换行的“结尾”(而不是新行)。 -line char),然后为每个输入行选择一个字符串进行修剪;但是,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~$
#29 楼
您也可以使用此方法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 next line until the
last line.
流量:
当第一次从输入获取行,进行交换,因此1进入保留空间,\ n进入模式空间,然后将保留空间附加到模式空间,然后执行替换并删除模式空间。
第二次进行线交换,2进入保留空间,1进入模式空间,然后
G
将保持空间附加到模式空间中,然后h
将模式复制到其中,并进行替换并删除。继续此操作,直到达到eof,然后打印出准确的结果。评论
但是,请注意回显'Y'| sed'x; G; 1!h; s / \ n / X / g; $!d'的结果为XY。
–诡异
2015年3月13日在1:41
#30 楼
另一种GNUsed
方法,与Zsolt Botykai的答案几乎相同,但是使用了sed
较少使用的y
(音译)命令,该命令节省了一个字节的代码(尾随g
):sed ':a;N;$!ba;y/\n/ /'
人们希望
y
的运行速度比s
快(也许以tr
的速度运行,快20倍),但是在GNU sed v4.2.2中,y
比s
慢约4%。更多便携式BSD
sed
版本:sed -e ':a' -e 'N;$!ba' -e 'y/\n/ /'
评论
使用BSD sed时y快约15%。有关工作示例,请参见此答案。
–雷神
16年11月3日在19:01
同样,对于BSD来说,sed命令需要在标签后终止,因此sed -e':a'-e'N; $!ba'-e'y / \ n / /'是解决方法。
–ghoti
18/09/13在4:26
评论
如果将单个字符替换为单个字符,tr才是工作的正确工具,而上面的示例显示了用空格替换换行符。因此在上面的示例中,tr可以工作。但是稍后会受到限制。 br />tr是正确的工作工具,因为发问者想用空格替换每个换行符,如他的示例所示。换行符的替换对于sed来说是唯一的奥秘,但tr可以轻松完成。这是一个常见的问题。执行正则表达式替换不是由tr而是由sed完成,这将是解决其他问题的正确工具。
“ tr”也可以只删除换行符`tr -d'\ n'`,但是您可能还希望删除返回值以更通用`tr -d'\ 012 \ 015'`。
警告:在Linux和较旧的Solaris计算机(EG sol5.8)之间的字符范围方面,“ tr”的行为不同。 EG:`tr -d'a-z'`和`tr -d'[a-z]'`。为此,我建议您使用没有差别的“ sed”。
@MikeS感谢您的回答。在tr'\ 012'''后面加上回声。否则,文件中的最后一个换行符也会被删除。 tr'\ 012'''<文件名;回响这招。