如何使用sed将LF替换为空格,但不替换CRLF?

5

我有一个csv文件,里面混杂着CRLFLF。有些地方出现了LF,实际上这些内容应该属于前一行。

例如:

smith;pete;he is very nice;1990CRLF
brown;mark;he is very nice;2010CRLF
taylor;sam;he isLF
very nice;2009CRLF

在我的脚本中,我想要删除所有单独的LF实例。我尝试使用sed:

sed -e ':a' -e 'N' -e '$!ba' -e 's/\n/ /g' $my_file

这种解决方案的问题在于,属于CRLFLF也会被替换为空格字符。

你能否尝试一下使用Unicode来表示“LF”? - Neeraj Wadhwa
使用GNU sed,您可以使用sed ':a;N;$!ba;s/\r\n/<<<CRLF>>>/g;s/\n/ /g;s/<<<CRLF>>>/\r\n/g;' my_file命令,但只有在文件不太大的情况下才能使用。 - Wiktor Stribiżew
2个回答

4

Perl默认不移除记录分隔符,因此可以很容易地进行操作。

$ cat -A ip.txt
smith;pete;he is very nice;1990^M$
brown;mark;he is very nice;2010^M$
taylor;sam;he is$
very nice;2009^M$

$ perl -pe 's/(?<!\r)\n/ /' ip.txt
smith;pete;he is very nice;1990
brown;mark;he is very nice;2010
taylor;sam;he is very nice;2009

$ perl -pe 's/(?<!\r)\n/ /' ip.txt | cat -A
smith;pete;he is very nice;1990^M$
brown;mark;he is very nice;2010^M$
taylor;sam;he is very nice;2009^M$

(?<!\r)\n 使用负向回顾来确保我们仅在\n不是由\r前导时才替换它。


修改 OP 的尝试:

$ sed -e ':a' -e 'N' -e '$!ba' -e 's/\([^\r]\)\n/\1 /g' ip.txt
smith;pete;he is very nice;1990
brown;mark;he is very nice;2010
taylor;sam;he is very nice;2009

\([^\r]\)用于确保紧接在\n之前的字符不是\r


3

使用 awk:

$ awk 'BEGIN{RS=ORS="\r\n"}/\n/{sub(/\n/,"")}1' file
smith;pete;he is very nice;1990
brown;mark;he is very nice;2010
taylor;sam;he isvery nice;2009

解释:

$ awk '
BEGIN { RS=ORS="\r\n" }  # set the record separators to CRLF
/\n/ {                   # if there is stray LF in the record
    sub(/\n/,"")         # remove it (maybe " " to replace it with a space)
}1' file                 # output it

已成功测试gawk、mawk和Busybox awk。在BSD awk上失败,例如使用:

awk '!/\r$/{printf "%s",$0;next}1' file

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接