2013-01-22 27 views
1

我正在寫一個JavaScript代碼來解析一些語法文件,這是相當多的代碼,但我會在這裏發佈相關信息。我正在使用Javascript正則表達式來匹配一個字符串中的重複行。該字符串包含,例如(假設字符串名稱是線):Javascript正則表達式重複行匹配不能正常工作

 

    if 
    else 
    ; 
    print 
    { 
    } 
    test1 
    test1 
    = 
    + 
    - 
    * 
    /
    (
    ) 
    num 
    string 
    comment 
    id 
    test2 
    test2 

應該發生什麼,是「測試1」和「測試2」找到了一個匹配。然後它應刪除重複項,並留下1個test1和test2實例。發生的事情根本不匹配。我對我的正則表達式很有信心,但是JavaScript可能會做我不期待的事情。以下是對上述字符串進行處理的代碼:

var rex = new RegExp("(.*)(\r?\n\1)+","g"); 
var re = '/(.*)(\r?\n\1)+/g'; 

rex.lastIndex = 0; 


var m = rex.exec(lines); 
    if (m) { 
     alert("Found Duplicate"); 
     var linenum = lines.search(re);   //Get line number of error 
     alert("Error: Symbol Defined twice\n"); 
     alert("Error occured on line: " + linenum); 
     lines = lines.replace(rex,"");   //Gets rid of the duplicate 
    } 

它從不進入if(m)語句。因此找不到匹配。我在這裏測試了正則表達式:http://regexpal.com/在我的代碼中使用正則表達式以及提供的示例文本。它匹配得很好,所以我有點不知所措。如果有人能幫上忙,那會很好。

謝謝。

編輯: 忘了補充,我正在測試這個在Firefox中,它只能在Firefox中工作。不知道這是否重要。

回答

0
var str = 'if\nelse\n;\nprint\n{\n}\ntest1\ntest1\n=\n+\n-\n*\n/\n(\n)\nnum\nstring\ncomment\nid\ntest2\ntest2\ntest2\ntest2\ntest2'; 
console.log(str); 
str = str.replace(/\r\n?/g,''); 
// I prefer replacing all the newline characters with \n's here 
str = str.replace(/(^|\n)([^\n]*)(\n\2)+/g,function(m0,m1,m2,m3,ind) { 
    var line = str.substr(0,ind).split(/\n/).length + 1; 
    var msg = '[Found duplicate]'; 
    msg += '\nFollowing symbol defined more than once'; 
    msg += '\n\tsymbol: ' + m2; 
    msg += '\n\ton line ' + line; 
    console.log(msg); 
    return m1 + m2; 
}); 
console.log(str); 

否則,您可以跳過第一行,換着花樣爲

/(^|\r\n?|\n)([^\r\n]*)((?:\r\n?|\n)\2)+/g 

注意[^\n]*也將趕上多個空行。如果你想確保它匹配(並替換)非空行,那麼你可能想要使用[^\n]+

[編輯]

對於記錄,每個m表示各arguments對象,所以m0是整個匹配,m1是第一子組((^|\n)),m2是第二子組(([^\n]*))和m3是最後一個子組((\n\2))。我本來可以用arguments[n]代替,但是這些更短。

與返回值一樣,由於Javascript使用的正則表達式中沒有lookbehind,這個模式捕捉到一個可能的前面的換行符(除非它是第一行),所以它需要返回匹配和前一個換行符如果有的話。這就是爲什麼它不應該只返回m2

+0

m0,m1,m3的功能是什麼?該函數返回m1 + m2,但是這會保持什麼值?我沒有看到m1在任何地方使用。 – Dohrann

+0

@Dohrann我在所有人的回答中都加入了這個解釋,以瞭解這些論點發生了什麼。 – inhan

+0

我現在明白了,謝謝,雖然這匹配在'18和20行'。因此,它與之後的第一個「test2」和「空白」空白相匹配。這我不明白。另外,替換不能正確替換,字符串仍然返回以前的內容。 – Dohrann

0

第一個錯誤\在一個JS字符串中也是一個轉義字符。

var rex = new RegExp("(.*)(\r?\n\1)+","g"); 

應該寫

var rex = new RegExp("(.*)(\\r?\\n\\1)+","g"); 
// or, shorter: 
var rex = /(.*)(\r?\n\1)+/g; 

如果要使其工作。在構造函數RegExp的情況下,您將該模式作爲字符串傳遞給構造函數。這意味着您需要轉義模式中發生的每個\反斜槓。如果使用regexp文字,則不需要轉義它們,因爲它們不在字符串中,而是將它們的「常規」屬性保留爲正則表達式模式。

二錯誤,你的表達

var re = '/(.*)(\r?\n\1)+/g'; 

是錯誤的。你在這裏做的是將一個字符串文字分配給一個變量。我假設你的意思是分配正則表達式的文本,這應該這樣寫:

var re = /(.*)(\r?\n\1)+/g; 

第三個錯誤:最後一行

lines = lines.replace(rex,"");   //Gets rid of the duplicate 

刪除這兩種情況下的全部重複行!如果你想保持每個重複的第一個實例,你應該使用

lines = lines.replace(rex, "$1"); 

最後,此方法只偵測到兩張連續相同的行。這是你想要的,還是你需要檢測任何重複,無論他們在哪裏?

+0

是的,它只需要檢測連續的相同的線。我記得把var re = // g更改爲var re ='// g',但我不確定爲什麼,這是一個錯誤。有了轉義角色,我甚至沒有想到這是一個字符串,我不得不逃避它們。感謝您的回覆,我會更新,如果我得到它的工作。 – Dohrann

相關問題