【问题标题】:Inverse of Perl regex X modifierPerl 正则表达式 X 修饰符的逆
【发布时间】:2011-05-14 18:35:17
【问题描述】:

我想使用 Perl 正则表达式来匹配这样的字符串:

spaM
s p a m
sp Am
S   p a   m

看看 Perl 的 x 修饰符,我应该可以做到这一点:

<?php
echo preg_match('#spam#ix', 's p a   m');
?>

但这会打印出 0(假)。 x 修饰符实际上忽略了正则表达式上的空格,而不是正在分析的字符串。我该怎么做呢?也就是说,忽略正在分析的字符串上的空格而不是我的正则表达式?我知道有多种方法可以做到这一点,例如首先从字符串中删除所有空格,但我想知道是否有强大的一步正则表达式解决方案。

【问题讨论】:

    标签: php regex perl spam-prevention


    【解决方案1】:

    说实话,我认为你最好去掉空格然后匹配。由于这就是您要执行的操作,因此您的代码将比找到一个神奇的正则表达式或在字母之间注入空白模式更清晰。

    Perl 看起来像这样。

    my $string = "S   p A m";
    (my $string_no_ws = $string) =~ s/\s//g;
    if ($string_no_ws =~ /spam/i) {
      #do something
    }
    

    如果你愿意,实际上你可以在没有正则表达式的情况下进行测试,使用index:

    my $string = "S   p A m";
    (my $lc_string_no_ws = lc $string) =~ s/\s//g;
    if (index($lc_string_no_ws, 'spam') >= 0) {
      #do something
    }
    

    【讨论】:

    • 这比其他答案更干净、更高效。
    【解决方案2】:

    #x 修饰符正好相反。它允许在正则表达式中使用无关的空格,搜索时会忽略它:

    preg_match('# s p a m #ix')
    

    只会匹配“垃圾邮件”。

    要使用正则表达式查找任意空格,您需要在任意字母之间注入 \s*:

    preg_match('# S \s* P \s* A \s* M #ix', 's p a   m');
    

    您可以通过以下方式将单词转换为适当的正则表达式并混合\s*,从而稍微自动化/简化这一点:

    $regex = join('\s*', str_split("spam", 1));
    preg_match("#$regex#ix", "s p a m");
    

    【讨论】:

    • 他们应该发明一些东西来在正则表达式中完成这一切。在我们这个时代,很大一部分 Web 开发都在与垃圾邮件作斗争。
    • @JoJo,维护垃圾邮件术语和转换列表不是正则表达式引擎的工作,而是模块的工作。
    • @JoJo,从字符串中删除空格可能比在模式中容纳它们更容易。
    • @ikegami:确实如此。这也是 mod_security 所做的(首先标准化/解码,然后探测)。不过要看上下文。如果您还想检查单词边界(在这种情况下不确定),那么删除空格可能是有害的。 (曾经写过一个垃圾邮件的 PHP 端口。这里有很多优点和缺点。)
    【解决方案3】:

    /x 在 perl 中修改正则表达式是指正则表达式结构,而不是匹配的内容。匹配你想要的值

    /s\s*p\s*a\s*m\s*/i
    

    如果顺序对垃圾邮件这个词很重要,如果不是,那么类似

    /[spam \t\n\r]+/ 
    

    足够了

    【讨论】:

    • “maps”、“spa”、“sap”等等真的不应该被视为与“spam”同一个词!
    • 嗯,不,因此它们不是“顺序无关紧要”的区别
    • 你说“如果顺序很重要”(强调我的)。我指出顺序确实很重要。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-01-13
    • 1970-01-01
    • 2012-07-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多