我有一个正则表达式来匹配用户名(使用preg_match
在PHP中运行):
/[a-z]+(?(?=\-)[a-z]+|)\.[1-9][0-9]*/
此模式与abc.124
,abc-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()”不起作用?
答案 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.124
和abc-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]*
的下一部分,后者成功。