问题
我有一个充满行的文件,例如
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
这 。转换为/up 直到第一个正斜杠
问题
如何编写正则表达式搜索和替换来解决我的问题?
尝试的解决方案
我尝试使用 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
这个问题有更直接的解决方案吗?
最佳答案
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
结果是一样的。
关于正则表达式,搜索和替换直到某一点,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/16095437/