在sed中是否有替代负面展望

时间:2017-04-08 22:45:19

标签: regex sed regex-lookarounds

sed我希望能够匹配/js/但不能/js/m我无法匹配/js/[^m],因为这会匹配/js/加上任何角色来后。负向前看在sed中不起作用。或者我会做/js/(?!m)并称它为一天。有没有办法用sed来实现这个目的,这种方法适用于大多数类似的情况,你想要一段不在另一段文本中结束的文本?

对于我想做的事情,有没有比sed更好的工具?可能是一个允许向前看的人。 awk使用自己的语言似乎有点太多了。

1 个答案:

答案 0 :(得分:2)

嗯,你可以这样做:

$ echo 'I would like to be able to match /js/ but not /js/m' |
    sed 's:@:@A:g; s:/js/m:@B:g; s:/js/:<&>:g; s:@B:/js/m:g; s:@A:@:g'
I would like to be able to match </js/> but not /js/m

当你找到/ js /时,你没有说出你想做什么,所以我只是把<>放在它周围。这将适用于所有UNIX系统,不像perl解决方案,因为不保证perl可用,并且不保证你可以安装它。

我上面使用的方法是sed,awk等中常见的习惯用法,用于创建输入中不存在的字符串。只要在您真正感兴趣的字符串或正则表达式中没有出现@/js/使用哪个字符并不重要。 s/@/@A/g确保输入中@的每次出现后跟A。所以现在当我s/foobar/@B/g foobar时,我已用@B替换@B的每一次出现,我知道每个foobar代表@,因为所有其他A s/foo/whatever/ }后跟foo。所以现在我可以foobar而不会跳过s/@B/foobar/g; s/@A/@/g中出现的sed 's:/js/m:\n:g; s:/js/:<&>:g; s:\n:/js/m:g' 。然后我用\n解开最初的替换。

在这种情况下,虽然您没有使用多行保留空间,但您可以更简单地使用:

sed 's:/js/m:\
:g; s:/js/:<&>:g; s:\
:/js/m:g'

因为换行符分隔的字符串中不能有换行符。以上内容仅适用于支持使用T(n) = 2T(n-1)表示换行符(例如GNU sed)的seds,但是对于所有seds的可移植性应该是:

O(2^n)