【问题标题】:"eager" regexp matching“渴望”正则表达式匹配
【发布时间】:2011-07-24 04:09:02
【问题描述】:

我必须删除两个分隔符之间的字符串,即 从“123XabcX321”我想要“123321”。 对于一个简单的案例,我可以:

$_=<>;
s/X(.*)X//;
print;

但如果输入中存在歧义,例如“123XabcXasdfjXasdX321”,它将第一个 X 与最后一个 X 匹配,我得到“123321”,但我想要“123asdfj321”。 有没有办法指定与第一个有效的可能分隔符而不是最后一个匹配的“渴望”匹配?

【问题讨论】:

    标签: regex perl


    【解决方案1】:

    它通常被称为“不贪婪”,你放了一个 ?量词后:s/X(.*?)X//;

    【讨论】:

    • 在给出的示例中,/g 需要多次替换。
    • 我认为“非贪婪”是更常见的术语。无论如何,默认是贪婪匹配,而你想要相反。
    • 请注意,在 Gnu grep 中,您需要使用 --perl-regexp (-P) 作为惰性运算符(或使用以下方法)。 reference
    • 请注意:"XaXbXY" =~ /X(.*?)XY/ => aXb
    • @ikegami:知道什么,它完全按照它应该的方式工作吗?
    【解决方案2】:

    如果可以的话,避免使用非贪婪修饰符作为性能提示。使用它可能会导致“意外”结果,因为添加 ? 实际上并不会阻止 .* 匹配任何内容。例如,

    $ perl -le'print for "XaXbXY" =~ /X(.*?)XY/;'
    aXb
    

    为避免匹配X,您可以使用以下内容:

    s/X[^X]*X//g;
    

    如果X 确实大于一个字符,您可以使用以下内容:

    s/X(?:(?!X).)*X//g;
    

    【讨论】:

    • 有趣...我会试试的。就我而言,X 不止一个字符。我必须破译?:(?!X) tho
    • @GClaramunt, (?: ) 在正则表达式模式中就像在 Perl 中的 ( )。在这种情况下,它表明* 影响(?!X). 而不仅仅是.( ) 经常被滥用于此目的。
    • @GClaramunt, (?! ) 检查后面的内容是否与包含的模式不匹配。
    • 你为什么更喜欢那个?
    • @JohnS,我为什么不用(...).*?x(...) 来防止.* 匹配x?因为它没有。非贪婪提供了性能提示;这不是为了防止.* 匹配。将非贪婪用作性能提示以外的任何东西都是一种脆弱的技巧。
    猜你喜欢
    • 2010-11-22
    • 1970-01-01
    • 1970-01-01
    • 2017-12-04
    • 2015-01-12
    • 2019-03-30
    • 2011-05-01
    相关资源
    最近更新 更多