如何使用该命令将换行符 (" \n
")替换为空格 (" ") ?sed
我尝试失败:
sed 's#\n# #g' file
sed 's#^$# #g' file
我如何解决它?
如何使用该命令将换行符 (" \n
")替换为空格 (" ") ?sed
我尝试失败:
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
将此解决方案与 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
用于这个原本简单的问题是有问题的。有关更简单和适当的解决方案,请参阅此答案。
sed ':a;N;$!ba;s/\n/ /g' file
sed 将循环执行步骤 1 到 3,直到到达最后一行,使所有行都适合 sed 将替换所有 \n 字符的模式空间
所有替代方案,与sed不同,不需要到达最后一行即可开始该过程
用bash,慢
while read line; do printf "%s" "$line "; done < file
与perl,sed类似的速度
perl -p -e 's/\n/ /' file
with tr,比sed快,只能用一个字符替换
tr '\n' ' ' < file
使用paste,类似 tr的速度,只能用一个字符替换
paste -s -d ' ' file
与awk , tr类似的速度
awk 1 ORS=' ' file
像“echo $(< file)”这样的其他替代方法很慢,只适用于小文件,需要处理整个文件才能开始处理。
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”命令将下一行添加到模式空间;
(2) 使用'H'命令至少两次将当前行追加
到Hold space,然后
用x、g或G从hold space中检索行;或 (3) 使用地址范围(参见上文第 3.3 节)
来匹配两个指定地址之间的行。
选项 (1) 和 (2) 会将 \n 放入模式空间中,
可以根据需要对其进行寻址 ('s/ABC\nXYZ/alphabet/g')。使用 'N' 删除一行行的一个示例
出现在第 4.13 节
(“如何删除一个特定连续行的块?”)。
可以通过将删除命令更改为其他内容来修改此示例
,例如“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。
更短的 awk 替代方案:
awk 1 ORS=' '
awk 程序由包含条件代码块的规则组成,即:
condition { code-block }
如果省略代码块,则使用默认值:{ print $0 }
. 因此,1
被解释为真实条件并print $0
为每一行执行。
当awk
读取输入时,它根据 (Record Separator) 的值将其拆分为记录RS
,默认情况下是换行符,因此awk
默认情况下会逐行解析输入。RS
拆分还涉及从输入记录中剥离。
现在,当打印一条记录时,ORS
(输出记录分隔符)被附加到它上面,默认又是一个换行符。因此,通过更改ORS
为空格,所有换行符都更改为空格。
GNU sed 有一个选项 ,-z
用于空分隔的记录(行)。你可以打电话:
sed -z 's/\n/ /g'
谁需要sed
?这是bash
方法:
cat test.txt | while read line; do echo -n "$line "; done
为了使用 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
(或cat
,等)绝对不需要。(GNU)sed
和 (GNU)awk
结合使用时,可以完成您需要的任何文本处理的 99.9%。
流!=基于行。ed
是一个基于行的编辑器。sed
不是。有关差异的更多信息,请参阅sed 讲座。大多数人混淆sed
是基于行的,因为默认情况下,它在简单匹配的模式匹配中不是很贪婪 - 例如,在进行模式搜索和替换一个或两个字符时,它默认只替换第一个匹配它会找到(除非全局命令另有指定)。如果它是基于行而不是基于流的,甚至不会有全局命令,因为它一次只会评估行。尝试运行ed
;你会注意到不同之处。ed
如果您想遍历特定行(例如在 for 循环中),这非常有用,但大多数时候您只需要sed
.
话虽如此,
sed -e '{:q;N;s/\n/ /g;t q}' file
sed
在 GNU版本 4.2.1中工作得很好。上面的命令将用空格替换所有换行符。输入起来很丑陋而且有点麻烦,但它工作得很好。' {}
s 可以省略,因为它们只是出于理智的原因才包括在内。
我有这个问题。更重要的是,我需要在 BSD(Mac OS X)和 GNU(Linux 和Cygwin)上工作的解决方案,sed
并且tr
:
$ echo 'foo
bar
baz
foo2
bar2
baz2' \
| tr '\n' '\000' \
| sed 's:\x00\x00.*:\n:g' \
| tr '\000' '\n'
输出:
foo
bar
baz
(有尾随换行符)
它可以在 Linux、OS X 和 BSD 上运行——即使没有UTF-8支持或使用蹩脚的终端。
用于tr
将换行符与另一个字符交换。
NULL
(\000
或\x00
) 很好,因为它不需要 UTF-8 支持并且不太可能被使用。
用于sed
匹配NULL
如果需要,用于tr
换回额外的换行符
为什么我没有找到一个简单的解决方案awk
?
awk '{printf $0}' file
printf
如果您想用空格或其他分隔原始行,将打印没有换行符的每一行:
awk '{printf $0 " "}' file
带有 :a 标签的答案...
... 在命令行上的 freebsd 7.2 中不起作用:
(回声富;回声栏)| sed ':a;N;$!ba;s/\n/ /g' sed: 1: ":a;N;$!ba;s/\n/ /g": 未使用的标签 'a;N;$!ba;s/\n/ /g' 富 酒吧
但是,如果您将 sed 脚本放在文件中或使用 -e “构建” sed 脚本...
> (echo foo; 回声栏) | sed -e :a -e N -e '$!ba' -e 's/\n/ /g' 富吧
或者 ...
> cat > x.sed << eof
:a
N
$!ba
s/\n/ /g
eof
> (echo foo; echo bar) | sed -f x.sed
foo bar
也许 OS X 中的 sed 是类似的。
如果您不幸不得不处理 Windows 行尾,则需要删除\r
和\n
:
tr '\r\n' ' ' < $input > $output
我不是专家,但我想sed
你首先需要将下一行附加到模式空间中,bij 使用“ N
”。从书sed & awk的“高级 sed 命令”中的“多行模式空间”部分(Dale Dougherty 和 Arnold Robbins;O'Reilly 1997;预览中的第 107 页):
multiline Next (N) 命令通过读取新的输入行并将其附加到模式空间的内容中来创建多行模式空间。模式空间的原始内容和新的输入行由换行符分隔。嵌入的换行符可以通过转义序列“\n”在模式中匹配。在多行模式空间中,元字符“^”匹配模式空间的第一个字符,而不是任何嵌入换行符之后的字符。同样,“$”仅匹配模式空间中的最后一个换行符,而不匹配任何嵌入的换行符。执行 Next 命令后,控制权将传递给脚本中的后续命令。
来自man sed
:
[2地址]N
将下一行输入附加到模式空间,使用嵌入的换行符将附加的材料与原始内容分开。请注意,当前行号会发生变化。
我用它来搜索(多个)格式错误的日志文件,其中搜索字符串可能在“孤立”的下一行中找到。
针对上面的“tr”解决方案,在 Windows 上(可能使用 tr 的 Gnuwin32 版本),建议的解决方案:
tr '\n' ' ' < input
对我不起作用,它要么出错,要么由于某种原因实际上替换了 \nw/ '' 。
使用 tr 的另一个功能,“删除”选项 -d 确实有效:
tr -d '\n' < input
或 '\r\n' 而不是 '\n'
我使用混合方法来解决换行问题,方法是使用 tr 用制表符替换换行符,然后用我想要的任何内容替换制表符。在这种情况下,“
”因为我正在尝试生成 HTML 中断。
echo -e "a\nb\nc\n" |tr '\n' '\t' | sed 's/\t/ <br> /g'`
在某些情况下,也许您可以更改RS
为其他字符串或字符。这样,\n 可用于 sub/gsub:
$ gawk 'BEGIN {RS="dn" } {gsub("\n"," ") ;print $0 }' file
shell 脚本的强大之处在于,如果您不知道如何以一种方式执行它,您可以以另一种方式执行它。很多时候,你需要考虑的事情比对简单问题的复杂解决方案还要多。
关于 gawk 很慢......并将文件读入内存的事情,我不知道这一点,但对我来说 gawk 似乎当时只使用一行并且非常非常快(不像其他一些那么快,但编写和测试的时间也很重要)。
我处理 MB 甚至 GB 的数据,我发现的唯一限制是行大小。
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、 read、 [、 printf。
read
,[
和至少在 bash 中都是printf
内置的,但 POSIX 可能无法保证这一点,因此在某些平台上,每个输入字节可能会启动一个或多个新进程,这会减慢速度。即使在 bash 中,这个解决方案也只能达到大约 50 kB/s,因此它不适合大文件。
在 Ubuntu(bash、dash 和 busybox)、FreeBSD 和 OpenBSD 上测试。
您也可以使用此方法:
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.
当第一行从输入中得到时,进行交换,因此1
进入保持空间并\n
进入模式空间,将保持空间附加到模式空间,并执行替换并删除模式空间。
在第二行,进行交换,2
进入保持空间并1
进入模式空间,G
将保持空间附加到模式空间,h
将模式复制到其中,进行替换并删除。此操作一直持续到达到 EOF 并打印准确的结果。
使用allow查找和替换\n
sed -ie -z 's/Marker\n/# Marker Comment\nMarker\n/g' myfile.txt
标记
变成
# 标记注释
标记
您可以使用xargs
- 默认情况下它将替换\n
为空格。
但是,如果您的输入有任何大小写unterminated quote
,例如如果给定行上的引号不匹配,则会出现问题。
在 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
要删除空行:
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 实现中保留空间可能是有限的。
纯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>
在“正常”替换之后引入换行符的是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~$
另一种GNU方法,与 Zsolt Botykai的 answersed
几乎相同,但它使用了不太常用的(音译)命令,该命令节省了一个字节的代码(尾随):sed
y
g
sed ':a;N;$!ba;y/\n/ /'
人们希望y
运行速度比s
, 快(也许速度tr
快 20 倍),但在GNU sed v4.2.2 y
中比s
.
更便携的 BSD sed
版本:
sed -e ':a' -e 'N;$!ba' -e 'y/\n/ /'
sed '1h;1!H;$!d
x;s/\n/ /g' YourFile
这不适用于大文件(缓冲区限制),但如果有足够的内存来保存文件,它会非常有效。(更正H
->1h;1!H
在@hilojack 的好评之后)
另一个在读取时更改新行的版本(更多 cpu,更少内存)
sed ':loop
$! N
s/\n/ /
t loop' YourFile
这可能对您有用(GNU sed):
sed 'H;$!d;x;:a;s/^((.).*)\2/\1 /;ta;s/.//' file
该H
命令将换行符添加到模式空间,然后将结果附加到保留空间。sed 的正常流程是从每一行中删除以下换行符,因此这将在保留空间的开头引入一个换行符并复制文件的其余部分。一旦文件被放入保留空间,将保留空间与模式空间交换,然后使用模式匹配将所有原始换行符替换为空格。最后,删除引入的换行符。
这样做的好处是永远不会在 sed 命令中实际输入换行符。
选择:
sed 'H;$!d;x;y/\n/ /;s/.//' file
或者:
sed 'H;1h;$!d;x;y/\n/ /' file
cat file | xargs
为了完整起见
还有一个选择:
tr -s "[:space:]" " " < filename > filename2 && mv filename2 filename
用于tr -s
:
-s, --squeeze-repeats 将最后指定的 SET 中列出的重复字符的每个序列替换为该字符的一次出现
这使用单个空格替换文件中的所有空白序列,将结果写入新文件,然后将新文件重命名为原始名称。
@OP,如果你想替换文件中的换行符,你可以使用 dos2unix (或 unix2dox )
dos2unix yourfile yourfile
您还可以使用标准文本编辑器:
printf '%s\n' '%s/$/ /' '%j' 'w' | ed -s file
注意:这会将结果保存回file
.
与sed
这里的大多数答案一样,此解决方案必须首先将整个文件加载到内存中。
前面的大多数sed
命令示例在我的 Unix 机器中对我不起作用,并给我错误消息:
Label too long: {:q;N;s/\n/ /g;t q}
这适用于所有 Unix/Linux 环境:
line=$(while read line; do echo -n "$line "; done < yoursourcefile.txt)
echo $line |sed 's/ //g' > sortedoutput.txt
第一行将从文件中删除所有新行yoursourcefile.txt
并生成一行。第二个sed
命令将删除其中的所有空格。
这真的很简单......当我找到解决方案时,我真的很生气。又少了一个反斜杠。就是这个:
sed -i "s/\\\\\n//g" filename
这里sed
没有缓冲区(适合实时输出)。
示例:用\n
HTML 中的<br/>
break替换
echo -e "1\n2\n3" | sed 's/.*$/&<br\/>/'
以下内容比大多数答案简单得多。此外,它正在工作:
echo `sed -e 's/$/\ |\ /g' file`
sed -i ':a;N;$!ba;s/\n/,/g' test.txt
tr "\n" <file name>
试试这个:
echo "a,b"|sed 's/,/\r\n/'
在 sed 替换部分,键入反斜杠,按回车键转到第二行,然后以 /g' 结束:
sed 's/>/\
/g'
[root@localhost ~]# echo "1st</first>2nd</second>3rd</third>" | sed 's/>/\
> /g'
1st</first
2nd</second
3rd</third
[root@localhost ~]#