PHP和Javascript之间的正则表达式差异

PHP和Javascript之间的正则表达式差异,javascript,regex,Javascript,Regex,我在前段时间编写的lexer中发现了一个bug,它似乎在我的正则表达式中。我经常使用regex101,我经常忘记在左边从PHP改为Javascript。不管怎样,这是我的正则表达式: /([\w\.]*)([()]*)/g 现在,除了匹配大量的空白外,我还应该匹配字符串: (!one || !two) && three (!one || !two) && three "(!one || !two) && three".match(/[\w\.

我在前段时间编写的lexer中发现了一个bug,它似乎在我的正则表达式中。我经常使用regex101,我经常忘记在左边从PHP改为Javascript。不管怎样,这是我的正则表达式:

/([\w\.]*)([()]*)/g
现在,除了匹配大量的空白外,我还应该匹配字符串:

(!one || !two) && three
(!one || !two) && three
"(!one || !two) && three".match(/[\w\.]+|[()]/g);

["(", "one", "two", ")", "three"]
……关于:

一个
两个
三个

在PHP中,这个正则表达式的工作方式正是我想要的

在Javascript中,它不是!!!!为什么Javascript会给我这个

1
2)
3

我们的零件
两个
以相同的匹配结束

所以,我的问题是,如何匹配字符串:

(!one || !two) && three
(!one || !two) && three
"(!one || !two) && three".match(/[\w\.]+|[()]/g);

["(", "one", "two", ")", "three"]
…作为:

一个
两个
三个

…在Javascript中使用正则表达式上的
string.match()


谢谢

根本原因是这个正则表达式可以匹配空字符串,不同的引擎处理这些情况的方式不同。在JS中,如果发现长度为零的匹配,您很可能会使用regex101方法手动推进索引,而不检查下一个字符是否是有效匹配的开始

要解决这个问题,需要确保正则表达式与空字符串不匹配。因此,您可以使用alternation,将一部分与
+
一起使用,另一部分与
*
量词一起使用,在alternative分支中交换它们:

([\w\.]+)([()]*)|([\w\.]*)([()]+)
看。在JS代码中,您需要应用一些逻辑来获得正确的值:

var re=/([\w\.]+)([()]*)|([\w\.]*)([()]+)/g;
变量str='(!一| |!二)&三';
var-res=[];
while((m=re.exec(str))!==null){
if(m[4]){res.push(m[4]);}
else如果(m[3]){res.push(m[3]);}
else如果(m[2]){res.push(m[2]);}
else{res.push(m[1]);}
}
document.body.innerHTML=“+JSON.stringify(res,0,4)+”
(!one || !two) && three 
所以,我的问题是,如何匹配字符串:

(!one || !two) && three
(!one || !two) && three
"(!one || !two) && three".match(/[\w\.]+|[()]/g);

["(", "one", "two", ")", "three"]
…作为:

一个
两个
三个

…在Javascript中使用正则表达式

详情如下:

\w+|\(|\)
为什么Javascript会给我这个

原始正则表达式
/([\w\.]*)([()]*)/g
匹配0个或多个单词字符或点,后跟0个或多个括号(
*
表示0个或多个)。实际上,您得到的不仅仅是像
two)
这样的东西,还有很多空字符串。为了得到你想要的,你需要使用交替,就像上面的例子:你想要单词chars或者括号

我猜您可能希望一次至少有一个单词字符和一个括号,因此我将单词字符选项中的量词修改为
+
,而括号选项中的量词则为零。

这里有一个简单的例子:

\w+|[()]
这是由“或”操作数“|”分隔的三个不同值

它正在寻找的三个值是:

  • 至少有一个'\w+'的任何字母数字字符
  • 一个左括号,记得用反斜杠“(”来转义它
  • 右括号,也转义为“')”
  • 然后,这将匹配每个单词以及左括号和右括号作为单独的匹配项

    或者可以使用括号作为括号,因为它们都是单个字符,因此不需要额外的转义


    使用您认为最清晰的一个,因为它将有助于将来的维护。

    只是一个注释:字符类中的
    ,不必转义,但有些用户喜欢双重保护:)我非常感谢您在这方面提出的倡议!不幸的是,您的正则表达式无效。谢谢你的努力,虽然你的正则表达式是无效的,但它根本不是真的。是的,它是Wiktor,请尝试在JS应用程序中使用它<代码>两个
    包含在同一个匹配中,就像我的问题一样。另外,他的代码片段以某种方式排除了
    two
    。结果应该是
    一个
    两个
    三个
    。他的代码片段提供了
    一个
    ,和
    三个
    。根据定义,这是无效的。当我在我的应用程序中使用他的正则表达式时,我从中得到了
    1
    2)
    ,和
    3
    。仍然无效,但与他的代码片段完全不同。我在JS应用程序中使用过它(请参阅我答案中的代码),它是JS可用形式的正则表达式。你接受的答案不是解决方案,而是解决问题的方法。太棒了!非常感谢。这正是我需要的,谢谢你的解释!真有趣!非常感谢。我错过了你在原文中的句号(或小数点),我看到有人已经给了你匹配三的答案。四作为一个匹配。。。[\w\.]+|[()]