我的文件中有很多像
这样的行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
这个问题是否有更直接的解决方案?
答案 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
这将找到斜杠的第一个实例,在其前面提取字符串的一部分,并对该部分执行音译。