【问题标题】:Regular expression in JavaScript not the same as in PHPJavaScript 中的正则表达式与 PHP 中的正则表达式不同
【发布时间】:2011-04-02 18:51:56
【问题描述】:

我有一个正则表达式来匹配用户名(在 PHP 中使用 preg_match 起作用):

/[a-z]+(?(?=\-)[a-z]+|)\.[1-9][0-9]*/

此模式匹配abc.124abc-abc.123 等形式的用户名。

但是,当我将其用于 JavaScript 时:

var re = new RegExp("/[a-z]+(?(?=\-)[a-z]+|)\.[1-9][0-9]*/"); 

我收到一个语法错误:

SyntaxError: Invalid regular expression: /[a-z]+(?(?=-)[a-z]+|).[1-9][0-9]*/: Invalid group

(?(?=\-)[a-z]+|) 是说如果在[a-z]+ 之后我们看到- 然后断言[a-z]+ 在它之后,否则,什么都不匹配。这一切在 PHP 中都很好用,但是我错过了什么不同的 JavaScript 呢?

编辑:我很欣赏 cmets,现在我有最后一个问题:

    var str="accouts pending removal shen.1206";
    var patt= new RegExp("/[a-z]+(?:-[a-z]+)?\.[1-9][0-9]*/"); 
    var result=patt.exec(str);
    alert(result); 

此警报显示为null?但是,如果我执行以下操作,它会起作用:

var patt=/[a-z]+(?:-[a-z]+)?\.[1-9][0-9]*/;
var result=patt.exec(str);
alert(result); 

为什么“new RegExp()”不起作用?

【问题讨论】:

标签: php javascript regex


【解决方案1】:

不同的正则表达式引擎支持不同的功能。 Conditionals 是 Javascript 的 not supported

无论如何,条件对于您的模式来说是不必要的。我会将您的表达式简化为 /[a-z]+(?:-[a-z]+)?\.[1-9][0-9]*/,这样更容易理解,并且可以在 PHP 的 PCRE 和 Javascript 中使用。

【讨论】:

    【解决方案2】:

    JavaScript 不使用与 PHP 相同的正则表达式实现。在这种情况下,JavaScript 不支持条件表达式(?(?=regex)then|else)(参见comparison of regular expression flavors)。但是您可以使用以下与您的等价的正则表达式:

    /[a-z]+(?:-[a-z]+)?\.[1-9][0-9]*/
    

    当使用RegExp 构造函数创建正则表达式(而不是regular expression literal syntax /…/)时,您也需要转义转义的\。所以:

    var re = /[a-z]+(?:-[a-z]+)?\.[1-9][0-9]*/;                 // OR
    var re = new RegExp("/[a-z]+(?:-[a-z]+)?\\.[1-9][0-9]*/");
    

    【讨论】:

      【解决方案3】:

      即使在 PHP 中,您的条件也不起作用。如果下一个字符是连字符,则前瞻 - (?=-) - 成功,但它不会使用连字符。然后[a-z]+尝试在同一个位置匹配失败,因为下一个字符还是-。您将不得不再次匹配连字符 - -[a-z]+ - 但正如其他人所说,无论如何您都不应该使用条件。

      条件是诱人的;它们似乎应该非常有用,但实际上它们很少有用。它们通过反映我们对某些问题的自然思考方式来引诱我们:“我想匹配一些字母,如果它们后面的字符是连字符,我想匹配它和更多的字母。”

      如果您学会思考更多像正则表达式的方式,您会省去很多麻烦:“我想匹配一大块字母,可选地后跟连字符和更多字母。”正则表达式实际上是自己写的:

      /[a-z]+(?:-[a-z]+)?/
      

      (您的正则表达式的 \.[1-9][0-9]* 部分很好;我将其省略了,以便我可以专注于条件方面。)


      编辑:要回答评论中的问题,是的,您的正则表达式匹配两种形式的字符串:abc.124abc-abc.123。但请看一下它匹配的字符串的哪个部分

      Array
      (
          [0] => Array
              (
                  [0] => abc.124
                  [1] => abc.123
              )
      
      )
      

      发生的情况是,第一个 [a-z]+ 最初与 abc-abc.123 中的第一个 abc 匹配。然后前瞻匹配 - 而不消耗它,第二个 [a-z]+ 尝试匹配连字符并失败,正如我之前所说的。

      由于未能在该位置找到匹配项,正则表达式引擎开始一次比对一个字符并再次尝试。当它到达第二个abc 时,第一个[a-z]+ 匹配它并移交给正则表达式的下一部分,即条件。

      输入字符串中的下一个字符是.,因此前瞻失败。条件不需要匹配任何内容,因为您没有为 else 子句提供子模式。因此,条件不匹配任何内容,并且控制传递到正则表达式的下一部分,\.[1-9][0-9]*,它成功了。

      【讨论】:

      • php > echo preg_match("/[az]+(?(?=\-)[az]+|)\.[1-9][0-9]*/"," sh-sh.123"); //echos 1 这在 php 中对什么不起作用?
      • @Chris:查看我的扩展答案。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-09-12
      • 2017-12-18
      • 2017-09-27
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多