【问题标题】:Regex match entire words only正则表达式仅匹配整个单词
【发布时间】:2017-07-08 19:21:10
【问题描述】:

我有一个正则表达式,用于查找给定内容块中的所有单词,不区分大小写,这些单词包含在存储在数据库中的词汇表中。这是我的模式:

/($word)/i

问题是,如果我使用/(Foo)/i,那么像Food 这样的词就会匹配。单词两边必须有空格或单词边界。

Foo 是句子开头、中间或结尾的单词时,如何修改我的表达式以仅匹配单词?

【问题讨论】:

    标签: regex word-boundary


    【解决方案1】:

    使用单词边界:

    /\b($word)\b/i
    

    或者,如果您正在搜索“S.P.E.C.T.R.E.”就像 Sinan Ünür 的例子:

    /(?:\W|^)(\Q$word\E)(?:\W|$)/i
    

    【讨论】:

    • 当您发布时,我只是在输入此答案的手写版本。 :)
    • @RichardSimoes \b(<|>=)\b 不匹配 >=
    • @RichardSimoes 和 \b[-|+][0-9]+\b 匹配 +10 中的 43E+10。两个我都不想要。
    • 如果我想搜索未附加或不包含在任何其他单词中的单词怎么办。那么这个逻辑就行不通了
    • 如何获得数学比较运算符 >= 和
    【解决方案2】:

    要匹配任何整个单词,您可以使用模式(\w+)

    假设您使用的是 PCRE 或类似的东西:

    以上截图来自这个现场示例:http://regex101.com/r/cU5lC2

    将命令行上的任何整个单词与(\w+) 匹配

    我将在Ubuntu 12.10 上使用phpsh interactive shell 通过称为preg_match 的方法演示PCRE regex engine

    启动phpsh,将一些内容放入变量中,匹配word。

    el@apollo:~/foo$ phpsh
    
    php> $content1 = 'badger'
    php> $content2 = '1234'
    php> $content3 = '$%^&'
    
    php> echo preg_match('(\w+)', $content1);
    1
    
    php> echo preg_match('(\w+)', $content2);
    1
    
    php> echo preg_match('(\w+)', $content3);
    0
    

    preg_match 方法使用 PHP 语言中的 PCRE 引擎来分析变量:$content1$content2$content3 以及 (\w)+ 模式。

    $content1 和 $content2 至少包含一个单词,$content3 不包含。

    将命令行中的多个文字单词与(dart|fart) 匹配

    el@apollo:~/foo$ phpsh
    
    php> $gun1 = 'dart gun';
    php> $gun2 = 'fart gun';
    php> $gun3 = 'farty gun';
    php> $gun4 = 'unicorn gun';
    
    php> echo preg_match('(dart|fart)', $gun1);
    1
    
    php> echo preg_match('(dart|fart)', $gun2);
    1
    
    php> echo preg_match('(dart|fart)', $gun3);
    1
    
    php> echo preg_match('(dart|fart)', $gun4);
    0
    

    变量 gun1 和 gun2 包含字符串 dart 或 fart。 gun4 没有。但是,查找单词fart 匹配farty 可能是个问题。要解决此问题,请在正则表达式中强制执行单词边界。

    将命令行上的文字单词与单词边界匹配。

    el@apollo:~/foo$ phpsh
    
    php> $gun1 = 'dart gun';
    php> $gun2 = 'fart gun';
    php> $gun3 = 'farty gun';
    php> $gun4 = 'unicorn gun';
    
    php> echo preg_match('(\bdart\b|\bfart\b)', $gun1);
    1
    
    php> echo preg_match('(\bdart\b|\bfart\b)', $gun2);
    1
    
    php> echo preg_match('(\bdart\b|\bfart\b)', $gun3);
    0
    
    php> echo preg_match('(\bdart\b|\bfart\b)', $gun4);
    0
    

    所以它与前面的示例相同,只是内容中不存在带有\b 字边界的单词fartfarty

    【讨论】:

    • 上午,下午不是文字吗?
    【解决方案3】:

    使用\b 会产生令人惊讶的结果。您最好弄清楚一个词与其定义的区别,并将该信息整合到您的模式中。

    #!/usr/bin/perl
    
    use strict; use warnings;
    
    use re 'debug';
    
    my $str = 'S.P.E.C.T.R.E. (Special Executive for Counter-intelligence,
    Terrorism, Revenge and Extortion) is a fictional global terrorist
    organisation';
    
    my $word = 'S.P.E.C.T.R.E.';
    
    if ( $str =~ /\b(\Q$word\E)\b/ ) {
        print $1, "\n";
    }
    

    输出:

    编译 REx "\b(S\.P\.E\.C\.T\.R\.E\.)\b" 最终程序: 1:绑定 (2) 2:打开 1 (4) 4:准确(9) 9:关闭 1 (11) 11:绑定 (12) 12:结束(0) 锚定“S.P.E.C.T.R.E.”在 0(检查锚定) stclass BOUND minlen 14 在 sv 中猜测 REx "\b(S\.P\.E\.C\.T\.R\.E\.)\b" 对 "S.P" 的匹配开始 .E.C.T.R.E. (反情报特别执行官,... 找到锚定的 substr "S.P.E.C.T.R.E."在偏移量 0... start_shift: 0 check_at: 0 s: 0 endpos: 1 与STCLASS不矛盾... 猜测:在偏移量 0 处匹配 匹配 REx "\b(S\.P\.E\.C\.T\.R\.E\.)\b" 与 "S.P.E.C.T.R.E. (Special Exec 反情报用途,“... 0 | 1:绑定(2) 0 | 2:打开1(4) 0 | 4:精确 (9) 14 | 9:关闭1(11) 14 | 11:绑定(12) 失败的... 匹配失败 释放 REx: "\b(S\.P\.E\.C\.T\.R\.E\.)\b"

    【讨论】:

    • 我认为一个词通常是一个 \w 词,但很有趣。
    【解决方案4】:

    如果你是在记事本++中做的

    [\w]+ 
    

    会给你整个单词,你可以添加括号将它作为一个组来获取。示例:conv1 = Conv2D(64, (3, 3), activation=LeakyReLU(alpha=a), padding='valid', kernel_initializer='he_normal')(inputs)。我想将LeakyReLU 作为注释移到它自己的行中,并替换当前的激活。在记事本++中,这可以使用以下查找命令来完成:

    ([\w]+)( = .+)(LeakyReLU.alpha=a.)(.+)
    

    替换命令变为:

    \1\2'relu'\4 \n    # \1 = LeakyReLU\(alpha=a\)\(\1\)
    

    空格是为了在我的代码中保持正确的格式。 :)

    【讨论】:

      【解决方案5】:

      对于那些想要在他们的代码中验证枚举的人,您可以按照指南进行操作

      在 Regex World 中,您可以使用 ^ 开始一个字符串并使用 $ 结束它。将它们与| 结合使用可能是您想要的:

      ^(Male)$|^(Female)$

      它只会在MaleFemale 的情况下返回true。

      【讨论】:

      • ^$ 匹配一行的开头(分别是结尾),因此如果这些是该行中唯一的单词,您的示例将匹配 only
      • 这正是我想要验证枚举时想要的!有什么问题?
      【解决方案6】:

      使用单词边界\b,

      以下(使用四个转义)适用于我的环境:Mac、Safari 版本 10.0.3 (12602.4.8)

      var myReg = new RegExp(‘\\\\b’+ variable + ‘\\\\b’, ‘g’)
      

      【讨论】:

        【解决方案7】:

        获取字符串中的所有“单词”

        /([^\s]+)/g

        基本上^/s 表示空格(或匹配非空格组)
        不要忘记贪婪的g

        【讨论】:

          猜你喜欢
          • 2010-11-15
          • 2012-01-06
          • 1970-01-01
          相关资源
          最近更新 更多