【问题标题】:Search words in a string using Boolean operators (AND, OR, NOT) as Google does像 Google 一样使用布尔运算符(AND、OR、NOT)搜索字符串中的单词
【发布时间】:2013-02-09 02:53:09
【问题描述】:

我想使用“或”、“与”和“非”等运算符在具有“Google”风格的字符串中进行搜索。可以在正则表达式中模拟这个运算符吗?

例如,我想使用单词“Javascript”、“PHP”和“Perl”在给定的字符串中进行以下搜索。

  1. Javascript 和 PHP
  2. Javascript 而不是 PHP
  3. Javascript 和 PHP 和 Perl
  4. Javascript 和(PHP 或 Perl)

PS:我不介意区分大小写的问题,因为所有重要的语言都有一个选项。

在 cmets 之后编辑:很明显,可以使用多个模式匹配扫描运行任何布尔表达式,但是,在单个正则表达式中考虑解决方案是很有趣的。此外,“期待”功能允许 解决非常复杂的模式匹配问题。

【问题讨论】:

  • 您的意思是“是否可以在 single 正则表达式中执行此操作”。因为多次执行它当然是微不足道的,例如/Javascript/ and !/PHP/,或/Javascript/ and (/PHP/ or /Perl/)
  • 用很多正则表达式都是微不足道的,@TLP。然而,在单个正则表达式中执行它更灵活、高效和优雅,它只是一次解析。只需在数据库中的数百万条记录中提交此搜索即可。
  • 实际上,对您的示例字符串进行基准测试时,我发现两个单个正则表达式比您的组合快 75%。它可能更优雅,但不是更易读,也不是(必然)更有效。看到它here
  • 我经常看到有人提出关于 Stack Overflow 的问题,他们一心想通过在一个单一的、难以理解的表达式中编写复杂的条件来使 Perl 正则表达式引擎跳过障碍。它似乎与将 Perl 程序压缩为类似不透明的单行程序的决心相同。帮自己一个忙:以最清晰、最易于维护的方式编写代码,您可能会发现它也是最高效的。如果您发现性能不可接受,则进行一些分析以找出代码的哪一部分需要加速。花哨的代码是糟糕的代码。
  • @TLP,反对事实没有论据!然而,有时发现正则表达式的巨大威力是很有趣的。我喜欢在一个简单的例子中与社区分享这个

标签: php javascript regex perl


【解决方案1】:

是的!

感谢“期待” 运算符,它是在Perl 语言的正则表达式语法中引入的。 Perl RegEx 框架被许多语言使用​​,包括 PHPJavascript

Perl 中也存在 "look behind" 运算符,但 Javascript 不支持它。

下面,我用 JavaScript 语法为您的搜索展示正则表达式:

1- 搜索(“Javascript”和“PHP”)

       S = "Javascript is a client language and PHP is a server language";
       patt = /^(?=.*Javascript).*PHP/;    
       if ( S.match(patt) ) 
         document.write("Found it!"); 
       else 
          document.write("Not Found");

它会打印 “找到它”

2- 现在搜索(“Javascript”而不是“PHP”)

     S = "Javascript is a client language and PHP is a server language"; 
     patt = patt = /^(?!.*PHP).*Javascript/;
     if ( S.match(patt) ) 
       document.write("Found it!"); 
     else 
       document.write("Not Found");

它打印 "Not Found" 因为 PHP 包含在字符串中。

3-第三次搜索是("Javascript" and "PHP" and "Perl")

    S = "Javascript rules, PHP are in most server, however Perl is inspiring";
    patt = /^(?=.*Javascript)^(?=.*PHP).*Perl/;
    if ( S.match(patt) ) 
       document.write("Found it!"); 
    else 
       document.write("Not Found");

它会打印 “找到它!”

4-最后,最后一种情况是("Javascript" and ("PHP" or "Perl" em>))。 没有什么不同,我只是使用带括号(圆括号)的传统分组:

    S = "Javascript rules, however Perl is inspiring"; 
    patt = /^(?=.*Javascript)(.*PHP|.*Perl)/;
    if ( S.match(patt) ) 
       document.write("Found it!"); 
    else 
       document.write("Not Found");

它打印 “找到它!”,因为缺少 PHP,但 Perl 在字符串中。

在 cmets 之后编辑:

我承认了。 “向前看”的语法很糟糕。但是,这很容易理解。扫描仪看着但不走路!

        patt = /Bee (?=Gees)/;     // patt = patt1(?=patt2) => patt1 + patt2 
        S = "Bee Gees";
        if (S.match(patt)) 
              document.write('ok');  // print OK and cursor stops at "G"

这是积极的展望

       patt = /Bee (?!Gees)/;   // patt = patt1(?!patt2) => patt1 + Not (patt2) 
       S = "Bee Gees";         
       if (S.match(patt)) 
             document.write('ok'); // it does not match
       S = "Bee Goes";         
       if (S.match(patt)) 
             document.write('ok'); // print OK and cursor stops at "G"

那是消极的期待

好消息是 Patt2 可以是一个复杂的模式,包括分组、子分组等。

最后的解释:

  • .* : 0 个或多个字符
  • ^ : 如果是字符串的开头则匹配。它不会移动光标。
  • $ : 匹配如果是字符串的结尾。它不会移动光标。
  • (p1|p2|...) : 如果 p1p2 或 ... 匹配,则匹配。

所以

         patt = /^(?=.*Javascript).*PHP/; 

是一个正则表达式(/ 是一个正则表达式分隔符,作为字符串的引号),这意味着 向前看 到(跳转字符直到找到“Javascript”),如果它将会成功, 跳转字符直到找到“PHP” (请记住,向前看不会移动光标!) 即,如果扫描程序找到“Javascript”,“PHP”就匹配。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-11-25
    • 2017-09-20
    • 1970-01-01
    • 2016-07-03
    • 2012-12-04
    相关资源
    最近更新 更多