【问题标题】:Correct way to add comments to a Regular Expression in PHP在 PHP 中向正则表达式添加注释的正确方法
【发布时间】:2016-01-03 15:42:35
【问题描述】:

我正在尝试添加 cmets 以使正则表达式更清晰

// Strip any URLs (such as embeds) taken from http://stackoverflow.com/questions/6427530/regular-expression-pattern-to-match-url-with-or-without-http-www
$pattern =
    '(                               # First capturing group
            (http|https)             # Second capturing grout,matches wither http or https
        \:\/\/)?                     # End of first capturing group, matches :// exactly
        [                            # Match any char in the following list. the + after the closing bracke means greedy
            a-z                      # Any char between a and z
            A-Z                      # Any char between A and Z
            0-9                      # Any char between 0 and 9
            \.\/\?\:@\-              # ./?:@- literally ( any one of them )
            _=#                      # _=# any of these thre chars
        ]+                           # end of list
        \.                           # matches .
        (                            # third caturing group
            [                        # start of list
                a-z                  # Any char between a and z
                A-Z                  # Any char between A and Z
                0-9                  # Any char between 0 and 9
                \.\/\?\:@\-          # ./?:@- literally ( any one of them )
                _=#                  # _=# any of these thre chars
            ]                        # end of list
        )*                           # end of capturing group with greedy modifier';
$excerpt = preg_replace("/$pattern/x", '', $excerpt );

但我收到警告

警告:preg_replace():第 280 行中的未知修饰符“/”

我该怎么评论呢?

【问题讨论】:

  • 您可能必须将每个部分分开并使用 . 运算符将它们连接起来。
  • 你只能在字符类中使用 cmets。空格在字符类中总是很重要的,即使使用 x 修饰符。
  • 如果使用#作为分隔符,是否可以使用x修饰符制作cmets?

标签: php regex


【解决方案1】:

这可能不是最简洁的方法,但您可以将每个部分括在引号中并将它们连接起来。

这样的事情应该可以工作:

$pattern =
    '('.                             // First capturing group
        '(http|https)'.              // Second capturing grout,matches wither http or https
    '\:\/\/)?'.                      // End of first capturing group, matches :// exactly
    ...   

另外,我在 PHP 文档中找到了 this

所以我想这也可以,但是您正在使用 x 修饰符,并且应该已经可以使用了。

如果设置了 PCRE_EXTENDED 选项,则字符类之外的未转义 # 字符会引入一个注释,该注释一直持续到模式中的下一个换行符。

这表示字符集[...] 内的所有 cmets 均无效。

这是一个与PCRE_EXTENDED 修饰符一起使用的工作示例:

$pattern = '
    (                              # First capturing group
        (http[s]?)                 # Second capturing grout,matches wither http or https
    \:\/\/)?                       # End of first capturing group, matches :// exactly
    [a-zA-Z0-9\.\/\?\:@\-_=#]+     # [List Comment Here]
    \.                             # matches .
    (                              # third caturing group
        [a-zA-Z0-9\.\/\?\:@\-_=#]  # [List Comment Here]
    )*                             # end of capturing group with greedy modifier
';

【讨论】:

  • 正如其他人指出的,您需要在评论中删除或转义分隔符
  • 分隔符最好改成~
【解决方案2】:

这是in a comment on the php.net modifiers page提出的。

引用:

使用 /x 修饰符添加 cmets 时,不要在 cmets 中使用模式分隔符。在cmets区不可忽视。

在您的示例中,您的一个 cmets 中嵌入了字符串 ://。由于 PHP 似乎没有通过考虑标志来解析正则表达式分隔符,因此它认为这是一个问题。下面的代码也可以看到:

echo preg_replace('/
a #Com/ment
/x', 'e', 'and');

Demo

您需要更改定界符或转义 cmets 中的定界符。

【讨论】:

    【解决方案3】:

    虽然已经说过您的 sn-p 中的问题来自于在您的模式 cmets 中使用模式分隔符,但完全重构了模式以实现 D.R.Y.实践将使您的正则表达式更易于阅读和维护。

    1. 使用在您的模式中找不到的定界字符 - 这消除了可避免的转义。
    2. ((http|https)\:\/\/)? 可以简化为 (?:https?://)? 并在模式中仍然保持其可选状态。
    3. 您的字母数字字符类加上一个简短的符号列表可以简化为[\w./?:@=#-]+

    代码:

    // strip urls
    $pattern = <<<REGEX
    ~
    (?:https?://)?  # optionally, case-insensitively match http or https followed by colon, forwardslash, forwardslash
    [\w./?:@=#-]+   # greedily match one or more characters from this list: any letters, any number, underscore, dot, forwardslash, question mark, colon, ampersand, equals, hash, hyphen
    \.              # match a dot
    [\w./?:@=#-]*   # greedily match zero or more characters from this list: any letters, any number, underscore, dot, forwardslash, question mark, colon, ampersand, equals, hash, hyphen
    ~ix
    REGEX;
    
    $excerpt = preg_replace($pattern, '', $excerpt);
    

    在清理并消除模式中的所有臃肿之后,在声明模式之前将所有内联 cmets 封装为注释实际上可能会变得很有吸引力,因为这样可以将长行换行而不破坏您的模式。

    【讨论】:

      猜你喜欢
      • 2014-01-29
      • 2011-08-19
      • 2010-11-14
      • 2014-07-26
      • 2014-12-17
      • 2020-07-08
      • 1970-01-01
      • 1970-01-01
      • 2017-03-12
      相关资源
      最近更新 更多