正则表达式,搜索和替换,直到某一点

时间:2013-04-19 00:42:52

标签: regex perl lookbehind

问题

我的文件中有很多像

这样的行
convert.these.dots.to.forward.slashes/but.leave.these.alone/i.mean.it

我想搜索和替换以便我得到

convert/these/dots/to/forward/slashes/but.leave.these.alone/i.mean.it

。转换为/直到第一个正斜杠

问题

如何编写正则表达式搜索和替换以解决我的问题?

尝试解决方案

我尝试使用perl后面的外观,但是没有实现可变长度的外观

$ echo "convert.these.dots.to.forward.slashes/but.leave.these.alone/i.mean.it" | perl -pe 's/(?<=[^\/]*)\./\//g'
Variable length lookbehind not implemented in regex m/(?<=[^/]*)\./ at -e line 1.

解决方法

实现了可变长度预测,因此您可以使用这个脏技巧

$ echo "convert.these.dots.to.forward.slashes/but.leave.these.alone/i.mean.it" | rev | perl -pe 's/\.(?=[^\/]*$)/\//g' | rev
convert/these/dots/to/forward/slashes/but.leave.these.alone/i.mean.it

这个问题是否有更直接的解决方案?

2 个答案:

答案 0 :(得分:5)

s/\G([^\/.]*)\./\1\//g

\G是一个与前一个匹配结束时的点匹配的断言。这可以确保每个连续的匹配紧跟在最后一个匹配之后。

匹配

\G          # start matching where the last match ended
([^\/.]*)   # capture until you encounter a "/" or a "."
\.          # the dot

取代:

\1     # that interstitial text you captured
\/     # a slash

用法:

echo "convert.these.dots.to.forward.slashes/but.leave.these.alone/i.mean.it" | perl -pe 's/\G([^\/.]*)\./\1\//g'

# yields: convert/these/dots/to/forward/slashes/but.leave.these.alone/i.mean.it

或者,如果你是一个纯粹主义者,并且不想重新添加捕获的子模式 - 避免这可能更有效,但我不确定 - 你可以利用\K来限制“真实”匹配仅与.匹配,然后只需用/替换即可。 \K基本上“忘记”与该点匹配的内容,因此最终返回的最终匹配仅是\K之后的内容。

s/\G[^\/.]*\K\./\//g

匹配

\G        # start matching where the last match ended
[^\/.]*   # consume chars until you encounter a "/" or a "."
\K        # "forget" what has been consumed so far
\.        # the dot

因此,为替换而匹配的整个文本只是“.”。

取代:

\/      # a slash

结果是一样的。

答案 1 :(得分:2)

您可以使用substr作为左值并对其执行替换。或音译,就像我在下面所做的那样。

$ perl -pe 'substr($_,0,index($_,"/")) =~ tr#.#/#'
convert.these.dots.to.forward.slashes/but.leave.these.alone/i.mean.it
convert/these/dots/to/forward/slashes/but.leave.these.alone/i.mean.it

这将找到斜杠的第一个实例,在其前面提取字符串的一部分,并对该部分执行音译。