【问题标题】:Substitute all but the last occurrence using perl使用 perl 替换除最后一次之外的所有内容
【发布时间】:2018-03-29 19:27:40
【问题描述】:

我有一个字符串说"a/b/c/d/e",我想将除最后一个/ 之外的所有字符串替换为。即我的输出应该是a.b.c.d/e

我如何修改我的替代命令s/\//./g 来做同样的事情?另请注意,层次结构并不总是有 4 个“/”。可以是任意数字。

【问题讨论】:

    标签: regex perl substitution regex-greedy


    【解决方案1】:

    替换字符串后面有/的所有/;因此不包括最后一个/

    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;
    • 非常感谢。上述两个选项似乎都有效。我继续使用这个“s{/([^/]*)(?=/)}{.$1}g;”因为它看起来很普通
    • @ikegami 结果不是(在我的基准测试中),谢谢,补充。我的猜测是:[^/] 一个还必须复制它捕获的内容,而另一个则覆盖单个字符(并且.*? 不会回溯)。以防万一,我正在使用更长的字符串进行更多测试。
    • @zdim,捕获添加时间。不知道它是否会比你的字符串匹配两次更多。可能还取决于字符串的大小
    • @ikegami 更新,带有注释和更长的路径组件——它在不同的 perls 和机器上更加一致。谢谢,这很有趣。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-04-20
    • 2013-12-26
    • 2016-12-20
    • 2021-11-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多