【问题标题】:match word that contains "XYZ" and does not start with colon匹配包含“XYZ”且不以冒号开头的单词
【发布时间】:2020-05-11 09:15:57
【问题描述】:

我正在寻找与任何包含 XYZ 且不以冒号 : 开头的单词匹配的正则表达式模式。

例如,我想从This isXYZ a :exampleXYZa 仅匹配isXYZ

我的第一个想法是使用这个正则表达式模式:

/(?<!\:[^\s\r\t\n])XYZ/

基本上,一个否定的lookbehind 以确保事先没有没有空格的冒号。但是,这不起作用,因为lookbehind assertion must be fixed length

编辑:我也想支持 utf8。

【问题讨论】:

    标签: php regex utf-8


    【解决方案1】:

    你可以有一个像下面这样的正则表达式:

    /\b((?<!:)\w*XYZ\w*)\b/ui
    
    • \b之前和之后只是匹配一个单词边界。

    • ((?&lt;!:)\w*XYZ\w*) 中,我们检查任何包含XYZ 并且前面有零个或多个字符、后面有零个或多个字符的单词。借助负向回溯(?&lt;!:),我们确保它前面没有:

    • 如 cmets 中的 @unclexo 所述,您可以在末尾添加 u 修饰符以支持 UTF-8 序列匹配。 See here for more info.

    • 您还可以添加i 标志以进行不区分大小写的匹配。

    片段:

    <?php
    
    $tests = [
            'This isXYZ a :exampleXYZa',
            'isXYZ a :exampleXYZa abcXYZ',
            'isXYZ a :exampleXYZXYZa  abcXYZ',
            'XYZ',
            'XYZjdhf',
            'This isXYZ a example:XYZa',
            'äöüéèXYZ :äöüéèXYZäöüéè'
        ];
    
    foreach($tests as $test){
        if(preg_match_all('/\b((?<!:)\w*XYZ\w*)\b/ui',$test,$matches)){
            print_r($matches[0]);
        }
    }
    

    演示: https://3v4l.org/Y8SMj

    【讨论】:

    • @Nick 不错。我假设它不应该匹配,但让我们看看 OP 认为它是什么。
    • 感谢您的解决方案。使用\b 的缺点是\b 仅匹配ASCII 字符和非ASCII 字符之间的位置。这意味着不支持像äöüéè 这样的变音符号和许多其他变音符号。例如,This isäXYZ 他只会找到XYZ 而不是isäXYZ
    • @Adam 如果您在模式末尾添加u 标志,它应该可以工作。
    • @Adam 更新了我的答案。似乎也可以与 This isäXYZ 一起使用。
    • @Adam 您现在应该选择答案。谢谢
    猜你喜欢
    • 2021-02-10
    • 2019-04-04
    • 2019-08-06
    • 2021-09-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-09-23
    相关资源
    最近更新 更多