【发布时间】:2018-03-29 19:27:40
【问题描述】:
我有一个字符串说"a/b/c/d/e",我想将除最后一个/ 之外的所有字符串替换为。即我的输出应该是a.b.c.d/e。
我如何修改我的替代命令s/\//./g 来做同样的事情?另请注意,层次结构并不总是有 4 个“/”。可以是任意数字。
【问题讨论】:
标签: regex perl substitution regex-greedy
我有一个字符串说"a/b/c/d/e",我想将除最后一个/ 之外的所有字符串替换为。即我的输出应该是a.b.c.d/e。
我如何修改我的替代命令s/\//./g 来做同样的事情?另请注意,层次结构并不总是有 4 个“/”。可以是任意数字。
【问题讨论】:
标签: regex perl substitution regex-greedy
替换字符串后面有/的所有/;因此不包括最后一个/
perl -wE'$_ = q(a/b/c/d/e); s{/(?=.*?/)}{.}g; say'
这使用positive lookahead、(?=...) 来进一步断言/ 的存在(在.*? 之后),而不消耗任何东西。
另一种方法是使用否定字符类模式进行捕获(然后将其放回字符串中)并在前瞻中仅使用固定字符串 /
s{/([^/]*)(?=/)}{.$1}g;
上面的第一种方法是 / 匹配和对其余部分的前瞻结果更快。可能的原因是([^/]*) 方法中的捕获(并且它必须将其复制回字符串中),其中第一种方法会覆盖单个字符(.*? 不会回溯)。
基准测试:在 v5.10.1 和 v5.27.2(桌面)下快 126%,在 v5.16.1(新服务器)下快 110%。使用 4-10 个字符长的字符串对四个路径组件进行了测试。
感谢 ikegami 注意到这一点并提示并评论比较。
【讨论】:
s{/([^/]*)(?=/)}{.$1}g;
[^/] 一个还必须复制它捕获的内容,而另一个则覆盖单个字符(并且.*? 不会回溯)。以防万一,我正在使用更长的字符串进行更多测试。