RegExp的不明确的界面

时间:2011-03-31 13:48:22

标签: javascript regex syntax mozilla

有点奇怪。

var body="Received: from  ([195.000.000.0])\r\nReceived: from  ([77.000.000.000]) by   (6.0.000.000)"
var lastMath="";
var subExp = "[\\[\\(](\\d+\\.\\d+\\.\\d+\\.\\d+)[\\]\\)]"
var re = new RegExp("Received\\: from.*?"+subExp +".*", "mg");
var re1 = new RegExp(subExp , "mg");
while(ares= re.exec(body))
{
        print(ares[0])
        while( ares1 = re1.exec(ares[0]))
        {
            if(!IsLocalIP(ares1[1]))
            {
                 print(ares1[1]) 
                 lastMath=ares1[1];
                 break ;
            }
        }

}
print(lastMath)

输出:

Received: from ([195.000.000.0])
195.000.000.0
Received: from ([77.000.000.000]) by (6.0.000.000)
6.0.000.000
6.0.000.000

但我认为应该是:

Received: from ([195.000.000.0])
195.000.000.0
Received: from ([77.000.000.000]) by (6.0.000.000)
77.000.000.000
77.000.000.000

因为很明显“77.000.000.000”是第一位的。如果我评论“中断”,输出顺序是正确的。 我的代码出了什么问题?

1 个答案:

答案 0 :(得分:1)

请注意,Javascript(和大多数语言)中的正则表达式分组不适用于*+运算符的非常明显的行为。例如:

js>r = /^(ab[0-9])+$/
/^(ab[0-9])+$/
js>"ab1ab2ab3ab4".match(r)
ab1ab2ab3ab4,ab4    

在这种情况下,您获得匹配的最后一个组,就是这样。我不确定指定这种行为的位置,但它可能因语言而异。

编辑IsLocalIP()做了什么?


好吧,我认为问题与exec的状态有关(这可能就是我不使用它的原因;我使用String.match()) - 如果你要做的话这个,你需要手动将正则表达式的lastindex属性初始化为0,否则会出现这种情况:

function weird(dobreak)
{
  var s = "Received: from  ([77.000.000.000]) by   (6.0.000.000)"
  var re1 = /[\[\(](\d+\.\d+\.\d+\.\d+)[\]\)]/mg
  while (s2 = re1.exec(s))
  {
    writeln("s2="+s2);
    if (dobreak)
      break;
  }
}

产生这个结果:

js>weird(true)
js>weird(true)
s2=[77.000.000.000],77.000.000.000
js>weird(true)
s2=(6.0.000.000),6.0.000.000
js>weird(true)
js>

你会注意到同一个函数会得到三个不同的结果,这意味着有状态会因某些奇怪的原因而混淆(Javascript是以某种方式缓存/实现正则表达式吗?我使用的是使用Spidermonkey = Firefox的javascript引擎的JSDB)

因此,如果我将代码更改为以下内容:

function notweird(dobreak)
{
  var s = "Received: from  ([77.000.000.000]) by   (6.0.000.000)"
  var re1 = /[\[\(](\d+\.\d+\.\d+\.\d+)[\]\)]/mg
  re1.lastIndex = 0;
  while (s2 = re1.exec(s))
  {
    writeln("s2="+s2);
    if (dobreak)
      break;
  }
}

然后我得到了预期的行为:

js>notweird(true)
s2=[77.000.000.000],77.000.000.000
js>notweird(true)
s2=[77.000.000.000],77.000.000.000
js>notweird(true)
s2=[77.000.000.000],77.000.000.000