Javascript Regexp重复行匹配无法正常工作

时间:2013-01-22 12:33:47

标签: javascript regex duplicate-removal

我正在编写一个Javascript代码来解析一些语法文件,这是一些代码,但我会在这里发布相关信息。我使用Javascript Regexp来匹配字符串中的重复行。例如,字符串包含(假设字符串名称是行):


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

应该发生什么,是'test1'和'test2'上的匹配。然后应删除副本,留下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中工作。不确定这是否重要。

2 个答案:

答案 0 :(得分: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,此模式捕获可能的前一个换行符(除非它是第一行)所以它需要返回匹配和前一个换行符if任何。这就是为什么它不应该只返回m2

答案 1 :(得分: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构造函数的情况下,您将模式作为字符串传递给构造函数。这意味着您需要转义模式中出现的每个\反斜杠。如果使用正则表达式文字,则不需要转义它们,因为它们不在字符串中,而是在正则表达式模式中保留它们的“正常”属性。

第二个错误,你的表达

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");

最后,此方法仅检测两个连续相同的行。这是你想要的,还是你需要检测任何重复项,无论它们在哪里?