2012-11-30 23 views
5

我做了一個簡單的代碼在一個字符串捕獲特定組:Javascript中的正則表達式不像應該那樣貪婪?

/[a-z]+([0-9]+)[a-z]+/gi (n chars , m digts , k chars). 

code

var myString='aaa111bbb222ccc333ddd'; 
var myRegexp=/[a-z]+([0-9]+)[a-z]+/gi; 

var match=myRegexp.exec(myString); 
console.log(match) 

while (match != null) 
{ 
    match = myRegexp.exec(myString); 
    console.log(match) 
} 

結果是:

["aaa111bbb", "111"] 
["ccc333ddd", "333"] 
null 

但是且慢, 爲什麼他沒有嘗試bbb222ccc部分?

我的意思是, 它看到了aaa111bbb但他應該有嘗試bbb222ccc ...(這是貪婪!)

我缺少什麼?

此外

看着

while (match != null) 
    { 
     match = myRegexp.exec(myString); 
     console.log(match) 
    } 

它是怎麼發展到第二個結果? 起初有:

var match = myRegexp.exec(myString);

更高版本(在while循環)

match=myRegexp.exec(myString); 
match=myRegexp.exec(myString); 

它是相同線......在那裏它記住第一結果已經顯示?

+8

因爲第一場比賽後,該指數是在BBB已經通過了第一場比賽的結束,並沒有什麼留下以匹配「ccc333ddd」'的字符串的其餘部分。貪婪意味着'+'會嘗試儘可能匹配,而不考慮正則表達式的下一部分可以匹配它。 – Esailija

+0

嗨@Esailija是的,我已經明白了。但如果它像它說的那樣貪婪,那不是。 –

+0

@Esailija請貼上您的評論作爲答案。 –

回答

4

.exec當您使用g標誌時是有狀態的。該狀態保存在正則表達式對象的.lastIndex屬性中。

var myString = 'aaa111bbb222ccc333ddd'; 
var myRegexp = /[a-z]+([0-9]+)[a-z]+/gi; 
var match = myRegexp.exec(myString); 
console.log(myRegexp.lastIndex); //9, so the next `.exec` will only look after index 9 
while (match != null) { 
    match = myRegexp.exec(myString); 
    console.log(myRegexp.lastIndex); 
} 

的狀態可以通過設置.lastIndex0或由execing不同的字符串被重置了。例如re.exec("")將重置狀態,因爲狀態保持爲'aaa111bbb222ccc333ddd'

同樣適用於.test方法,因此如果您不喜歡沒有意外的情況,請不要使用g標誌,並使用正則表達式來使用.test。見https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/RegExp/exec

+0

這是否意味着,如果我不保留正則表達式在一個變量,並始終使用原始的'/ [az] +([0-9] +)[az] + /',它不會記住索引? –

+2

@RoyiNamir是的,當你創建一個新的正則表達式對象時,它還沒有任何狀態。換句話說,'/[a-z]+([0-9]+)[a-z]+/gi.lastIndex === 0' alwys – Esailija

+0

我不明白'test'部分。爲什麼我不應該用[g]來測試?因爲它產生> 1的結果? –

2

您也可以手動更新lastIndex屬性:

var myString='aaa111bbb222ccc333ddd'; 
var myRegexp=/[a-z]+([0-9]+)[a-z]+/gi; 

var match=myRegexp.exec(myString); 
console.log(match); 

while (match != null) 
{ 
    myRegexp.lastIndex -= match[0].length - 1; // Set the cursor to the position just after the beginning of the previous match 
    match = myRegexp.exec(myString); 
    console.log(match) 
} 

請參閱此鏈接MDN exec


編輯:

順便說你的正則表達式應該是:/[a-z]{3}([0-9]{3})[a-z]{3}/gi

+0

編輯後的lastIndex爲0。 –