Неоднозначный интерфейс RegExp - PullRequest
1 голос
/ 31 марта 2011

Нечто очень странное.

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» идет первым. Если я прокомментирую "break", порядок вывода правильный. Что не так с моим кодом?

1 Ответ

1 голос
/ 31 марта 2011

Обратите внимание, что регулярное выражение в Javascript (и большинстве языков) не работает с очень очевидным поведением с операторами * или +.Например:

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

В этом случае вы получите последнюю группу, которая соответствует, и все.Я не уверен, где указано это поведение, но оно может варьироваться от языка к языку.

edit : Что делает 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>

Обратите внимание, что то же самоеФункция получает три разных результата, что подразумевает, что statefulness портит вещи по какой-то причудливой причине (Javascript как-то кэширует / интернализует регулярное выражение? Я использую JSDB, который использует движок JavaScript Spidermonkey = Firefox).измените код на следующий:

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
...