JavaScript中的正则表达式与PHP中的正则表达式不同

时间:2010-08-23 17:45:05

标签: php javascript regex

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

/[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的不同之处是什么?

编辑:我很感谢这些评论,现在我对此有最后一个问题:

    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); 

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

3 个答案:

答案 0 :(得分:5)

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

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

答案 1 :(得分:3)

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]*/");

答案 2 :(得分:2)

即使在PHP中,您的条件也不起作用。如果下一个字符是连字符,那么前瞻 - (?=-) - 会成功,但它不会消耗连字符。然后[a-z]+尝试在同一位置匹配并失败,因为下一个字符仍为-。你必须再次匹配连字符 - -[a-z]+ - 但正如其他人所说的那样,你不应该使用条件。

条件诱人;他们似乎就像他们应该非常有用,但在实践中他们很少。他们通过镜像我们自然地思考某些问题的方式来引诱我们:“我想要匹配一些字母,如果跟随它们的字符是连字符,我想匹配它和更多字母。”

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

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

(你的正则表达式的\.[1-9][0-9]*部分很好;我把它留了出去,所以我可以专注于条件方面。)


编辑:要回答评论中的问题,是的,您的正则表达式匹配两种表单的字符串:abc.124abc-abc.123。但仔细看看它匹配的字符串 part

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

)

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

在该位置找不到匹配项后,正则表达式引擎开始一次向前突出一个字符并再次尝试。当它到达第二个abc时,第一个[a-z]+匹配它并移交到正则表达式的下一部分,即条件。

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