【发布时间】:2014-02-07 14:00:49
【问题描述】:
问题是,当所有传递的字符串合并为一个以匹配换行符时,如果输入有一个尾随换行符,sed 将无法匹配它。
一个简单的字符串。
$ echo -en "aa\nbb\ncc\ndd" | hexdump -C
00000000 61 61 0a 62 62 0a 63 63 0a 64 64 |aa.bb.cc.dd|
0000000b
在这种情况下,如果我们需要用空字符而不是换行符来包围最后两段文本,它可以正常工作。
$ echo -en "aa\nbb\ncc\ndd" \
| sed -rn '1h; 2,$ H; ${g; s/^(.*)\n([^\n]+)\n([^\n]+)$/\1\x00\2\x00\3\x00/; p}' \
| hexdump -C
00000000 61 61 0a 62 62 00 63 63 00 64 64 00 |aa.bb.cc.dd.|
0000000c
但如果输入有一个尾随换行符,则将尾随 \n 附加到替换正则表达式不会使其匹配。
$ echo -en "aa\nbb\ncc\ndd\n" \
| sed -rn '1h; 2,$ H; ${g; s/^(.*)\n([^\n]+)\n([^\n]+)\n$/\1\x00\2\x00\3\x00/; p}' \
| hexdump -C
00000000 61 61 0a 62 62 0a 63 63 0a 64 64 0a |aa.bb.cc.dd.|
0000000c
但是,如果我们没有在 regexp 中添加尾随换行符,它仍然匹配!
$ echo -en "aa\nbb\ncc\ndd\n" \
| sed -rn '1h; 2,$ H; ${g; s/^(.*)\n([^\n]+)\n([^\n]+)$/\1\x00\2\x00\3\x00/; p}' \
| hexdump -C
00000000 61 61 0a 62 62 00 63 63 00 64 64 00 0a |aa.bb.cc.dd..|
0000000d
但它似乎只是忽略了输入中的尾随换行符,或者$ 以某种方式与它本身匹配。我在sed FAQ on sourceforge(第 5.10 节)中发现,sed 在将尾随换行符放置到模式空间之前从行中删除尾随换行符,甚至在输出中添加尾随换行符,但是,从第二个和第三个可以清楚地看到例如,它不做任何事情。
所以我一直在阅读和阅读并回想$ 以某种方式与尾随\n 本身匹配。如果我正确理解了信息页面,它应该在多行模式下,即当替换具有 M 或 m 修饰符时。但事实并非如此。还提到了像\´(实际上是坟墓标记)和\'(直单引号)这样的组合,它们应该在多行模式下匹配缓冲区边界,但它们在我的shell(GNU bash-1.4.45)中不起作用它们有特殊的含义。
【问题讨论】:
-
至于最后一段尝试:
echo -en "aa\nbb\ncc\ndd" |sed 'N;N;N;s/\`/<<</;s/\'\''/>>>/'N.B.在 sed 命令周围使用单引号,必须引用\'。