很多人说我们可以在正则表达式中没有懒惰的量词,但我遇到了一个问题,没有它我无法解决(我在这里使用sed)。
我想要处理的字符串由以字速率分隔的子字符串组成,例如:
anfhwe9.<<76xnf9247 rate 7dh3_29snpq+074j rate 48jdhsn3gus8 rate
我想用3个破折号(---)替换那些子串(除了' rate '之外);结果应该是:
---rate---rate---rate
根据我的理解(我不知道Perl),可以使用惰性量词轻松完成。在vim中也有懒惰的量词;我是用这个命令做的
:s/.\{-}rate/---rate/g
\{-}
告诉vim尽可能少匹配。
但是,vim是一个文本编辑器,我需要在许多机器上运行脚本,其中一些机器没有安装Perl。如果您可以告诉正则表达式与.*[^(rate)]rate
之类的原子分组不匹配但是不起作用,也可以解决它。
任何想法如何使用POSIX正则表达式实现这一点,还是不可能?
答案 0 :(得分:3)
在这种情况下,我会使用split():
perl -n -e 'print join ("rate", ("---") x split /rate/)' [input-file]
答案 1 :(得分:2)
如果不使用延迟量词或负向前瞻(POSIX都不支持),这并不容易,但这似乎有效。
([^r]*((r($|[^a]|a([^t]|$)|at([^e]|$))))?)+rate
我模糊地回忆起POSIX角色类有点不耐烦。如果它们不符合POSIX标准,您可能需要更改该正则表达式中的字符类。
答案 2 :(得分:2)
是否有任何字符可以保证不在输入中?例如,如果'!' 不能发生,您可以转换输入以替换该唯一字符,然后对转换后的输入执行全局替换:
sed 's/ rate /!/g' < input | sed -e 's/[^!]*/---/g' -e 's/!/rate/g'
另一种方法是以类似的方式使用awk的split命令 上面的perl建议,假设awk比perl更可靠。
awk '
{ ans="---"
n=split($0, x, / rate /);
while ( n-- ) { ans = ans "rate---";}
print ans
}'
答案 3 :(得分:1)
您不关心子串的内容这一事实开辟了许多选择。例如,添加Bob Lied的建议 - 即使'!'可以在输入中出现,您可以将其更改为其他内容:
sed -e 's/!/./g' -e 's/rate/!/g' -e 's/[^!]\+/---/g' -e 's/!/rate/g' <input >output
答案 4 :(得分:0)
使用 awk :
awk -Frate '{
for (i = 0; ++i <= NF;)
$i = (i == 1 || i == NF) && $i == x ? x : "---"
}1' OFS=rate infile
答案 5 :(得分:0)
或者,awk 'BEGIN {OFS=FS="rate"} {for (i=1; i<=NF-1; i++) {$i = "---"}; print}'