问题

我有一个充满行的文件,例如

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/

10-12 16:48
查看更多