2013-08-16 254 views
0

我需要引用行尾并使用this解决方案来替换文件有多行时完美工作的行尾。sed:替换行尾

当我尝试使用这种方法的文件没有\n或单行以\n结尾时出现问题。在这种情况下,sed不会取代任何内容,即使第二个s/命令也不起作用。也看起来像线的末尾永远不会被取代。

我的命令是:

sed ':a;N;$!ba;s/\n/\\n/g;s/a/_/g' <file> 

(取代\n\\n和替换a_例如)。

我用hexdump -C在这里显示的文件:

有测试我做:

$ # Test1. single line without \n 
$ echo -n 'abc' | sed ':a;N;$!ba;s/\n/\\n/g;s/a/_/g' | hexdump -C 
00000000 61 62 63           |abc| 
# but expected "_bc" 

$ # Test2. single line with \n 
$ echo 'abc' | sed ':a;N;$!ba;s/\n/\\n/g;s/a/_/g' | hexdump -C 
00000000 61 62 63 0a          |abc.| 
# but expected "_bc\n" 

$ # Test3. two lines 
$ echo -e 'abc\n' | sed ':a;N;$!ba;s/\n/\\n/g;s/a/_/g' | hexdump -C 
00000000 5f 62 63 5c 6e 0a         |_bc\n.| 
# but expected "_bc\n\n" 

问题:为什么第二s/不能取代的Test1和Test2的东西吗?在所有这些测试中,是否有任何方法可以修复替换s/\n/\\n/s/a/_/g

P.S .:我不想要一些解决方法,比如在sed处理之前在流尾添加换行符,并在删除之后删除它。

编辑:看起来像N命令不会读取单行,即使它后跟'\ n'。任何想法如何解决它?

编辑2:看起来像这样是expected behavior of N command。有没有什么方法可以取代最后一行的结尾?

+0

我最近使用过这个:sed'{:q; N; s/\ n/_/g; t q}' – svante

+0

您是否尝试过分离sed部分? 'sed':a; N; $!ba' | sed的/ \ n/\\ n/g; s/a/_/g''或类似的。 – svante

+0

这没有帮助,因为它等于'cat | sed's/\ n/\\ n/g; s/a/_/g''。使用'':a; N; $!ba''连接线正在一个sed过程中工作。 – loentar

回答

0

伤心,但我没有找到任何方法来防止sed添加新行输出N命令时使用。我不想要一些解决方法,喜欢在处理之前添加新行并在删除之后删除它,但似乎没有其他方法。

这是解决方法,最终溶液:

sed ':a;$!{N;ba};s/\n/\\n/g;s/a/_/g' <<< "$VAR" | tr -d '\n' 

<<<状回声增加了新的行成的输入字符串,tr删除它。

随着该行所有测试都OK:

$ echo -e "abc" | sed ':a;$!{N;ba};s/\n/\\n/g;s/a/_/g' | tr -d '\n' | hexdump -C 
00000000 5f 62 63           |_bc| 

$ echo -e "abc\n" | sed ':a;$!{N;ba};s/\n/\\n/g;s/a/_/g' | tr -d '\n' | hexdump -C 
00000000 5f 62 63 5c 6e         |_bc\n| 

$ echo -e "abc\n\n" | sed ':a;$!{N;ba};s/\n/\\n/g;s/a/_/g' | tr -d '\n' | hexdump -C 
00000000 5f 62 63 5c 6e 5c 6e        |_bc\n\n| 

P.S:谢谢波东搞清楚的:a;$!{N;ba}

P.P.S .:如果有人会给出没有tr的工作答案,我会重新接受它。

2

你可以用perl代替吗?

$ echo -n "abc" | perl -pe 's/\n$/\\n/;' -pe 's/a/_a/;' | od -x 
0000000 615f 6362 
0000004 
$ echo "abc" | perl -pe 's/\n$/\\n/;' -pe 's/a/_a/;' | od -x 
0000000 615f 6362 6e5c 
0000006 
$ echo -e 'abc\n' | perl -pe 's/\n$/\\n/;' -pe 's/a/_a/;' | od -x 
0000000 615f 6362 6e5c 6e5c 
0000010 
+0

Bash是首选。不要只为一个大于30的脚本添加新的依赖关系。 – loentar

+0

@loentar你有没有出现在你的输入中的字符:) – devnull

+0

对不起,在“期望的结果”中有错别字,你的第二个正则表达式应该看起来像's/a/_ /;'它也可以组合成单个参数:'perl -pe's/\ n $/\\ n/g; s/a/_/g''。无论如何谢谢你的回答。 – loentar

3

这可能会为你工作(GNU SED):

sed ':a;$!{N;ba};s/\n/\\n/g;s/a/_/g' file 

或:

sed ':a;$!N;$!ba;s/\n/\\n/g;y/a/_/' file 

逻辑上是有道理的:一个人不能得到next行,如果你在last线。

+0

谢谢你的回答。我理解这个逻辑。不幸的是,它不会替换'\\ n'(Test2和Test3)的最后一行。可能没有办法使'N'读取不会跳过最后一行。 – loentar

+0

因为它不能读取不存在的行,只需添加一行! 'sed':a; $!{N; ba}; G; s/\/\\ n/g; s/a/_/g'文件 – potong

+0

不幸的是,这总是在源码流中添加新行,失败了。它也不会删除最后一行,所以所有的测试都失败了。 – loentar