使用正则表达式在Javascript中查找两个字符串之间的差异

12

正则表达式专家请帮忙看看是否可以用正则表达式解决此问题:

给定字符串1是任何字符串

而字符串2是包含字符串1所有部分的任何字符串(但不是简单匹配——我会举例说明)

如何使用正则表达式将字符串2中字符串1的所有部分替换为空白,以便剩下的是不在字符串1中的字符串?

例如: str1 = "test xyz"; str2 = "test ab xyz"

我想要得到" ab"或者"ab "。 我能写什么正则表达式,使得当我在str2上运行一个替换函数时,它会返回" ab"?

以下是一些非正则表达式代码:

            function findStringDiff(str1, str2) {
                var compareString = function(str1, str2) {
                    var a1 = str1.split("");
                    var a2 = str2.split("");
                    var idx2 = 0;
                    a1.forEach(function(val) {
                        if (a2[idx2] === val) {
                          a2.splice(idx2,1);
                        } else {
                            idx2 += 1;
                        }
                    });
                    if (idx2 > 0) {
                        a2.splice(idx2,a2.length);
                    }
                    return a2.join("");
                }

                if (str1.length < str2.length) {
                    return compareString(str1, str2);
                } else {
                    return compareString(str2, str1);
                }
            }

            console.log(findStringDiff("test xyz","test ab xyz"));

13
我不认为正则表达式在这里有任何帮助。 - Ja͢ck
3
这里展示的算法似乎会让'$1.00''00.1$'之间看起来没有区别。 - Ja͢ck
1
以上代码甚至认为“ab”和“cd”是相同的。 - Millie Smith
2
你能给出多个例子,这些例子不仅在一个字符上有所区别吗?现在还不清楚你想要什么。 - Millie Smith
1
好的。不客气。去了解正则语言,它就不会再神奇了。 - Millie Smith
显示剩余23条评论
4个回答

22

正则表达式只能识别字符串是否符合某种模式。它们不足以进行像您所要求的比较。您需要基于第一个字符串构建一种正则语言来识别第二个字符串,然后使用匹配组来抓取第二个字符串的其他部分并将它们连接在一起。以下是我认为可以以可读方式完成您所需的内容。

//assuming "b" contains a subsequence containing 
//all of the letters in "a" in the same order
function getDifference(a, b)
{
    var i = 0;
    var j = 0;
    var result = "";

    while (j < b.length)
    {
        if (a[i] != b[j] || i == a.length)
            result += b[j];
        else
            i++;
        j++;
    }
    return result;
}

console.log(getDifference("test fly", "test xy flry"));

这是它的jsfiddle:http://jsfiddle.net/d4rcuxw9/1/


我明白了。j是b的索引,i是a的索引。您正在循环遍历较长的字符串并将“未找到/不同”的字符存储在结果中。我喜欢这个方法。由于正则表达式不可行,我将把它标记为我的首选答案。谢谢Millie! - techguy2000
1
我知道我非常晚了,这个问题已经关闭了,但是以防万一有人想找到两个字符串之间的区别,而不考虑字符的顺序:https://jsfiddle.net/c8xchkxq/ - Pedro Corso
1
好的,简单明了的解决方案,谢谢!我需要在单词级别上做同样的事情,并且想要收到添加单词的位置。如果其他人有兴趣,请参见:http://jsfiddle.net/409doc37/ - Heribert

1
我觉得这个问题非常有趣。虽然我来晚了一点,但我想分享一下我的解决方法,它是通过使用正则表达式实现的。这个解决方案很简洁,但不太易读。
尽管我喜欢它的简洁性,但我可能不会在我的代码中使用它,因为它的难懂程度降低了可维护性。
var str1 = "test xyz",
    str2 = "test ab xyz"
    replacement = '';
var regex = new RegExp(str1.split('').map(function(char){
    return char.replace(/[.(){}+*?[|\]\\^$]/, '\\$&');
}).join('(.*)'));
if(regex.test(str2)){
    for(i=1; i<str1.length; i++) replacement = replacement.concat('$' + i);
    var difference = str2.replace(regex, replacement);
} else {
    alert ('str2 does not contain str1');
}

""test xyz"的正则表达式是/t(.*)e(.*)s(.*)t(.*) (.*)x(.*)y(.*)z/,而replacement"$1$2$3$4$5$6$7"

虽然代码不再简洁,但现在它可以处理包含特殊字符的str1了。

"

我最初认为str1的字符限制为10个。但我刚学到JavaScript允许使用大于9的数字进行反向引用。 - Lorenz Meyer
这无法区分 test xyztest xy 以及 test{2 spaces}xyztest xyz 之间的差异。 - James Wilkins
@LorenzMeyer 我非常兴奋。我认为你发现了一些东西。但是当我使用var str1 =“$ 1.00”,str2 =“$ 1..00”时,它没有找到点。我希望你能想出一个强大的解决方案 - 所以你正在根据str1输入动态构建正则表达式,这很有趣... - techguy2000
@james str1必须包含在str2中。您的示例与var str1 ='test xy',str2 ='test xyz';var str1 ='test xyz',str2 ='test xyz';有效。这是导致投票下降的原因吗? - Lorenz Meyer
1
@LorenzMeyer 你是不是更新了代码以处理像点或美元符号这样的特殊字符?我尝试了点和美元符号,但代码没有起作用。http://jsfiddle.net/mnzhbz7o/ - techguy2000
显示剩余8条评论

-2

如果你想查找是否有额外的'.',可以这样做:

result = "$1...00".match(/\$1\.(\.*)?00/)[1];

result 是找到的额外 '.'。你不能仅使用正则表达式比较字符串。也许可以使用它,然后比较结果。

你也可以尝试这个:

result = "$1...00".match(/(\$)(\d+)\.(\.*)?(\d+)/);
// Outputs: ["$1...00", "$", "1", "..", "00"]

这将提取各个部分以进行比较。


-2

如果您只关心测试给定字符串是否包含两个或更多连续的点 '.' 字符:

var string = '$1..00',
    regexp = /(\.\.+)/;

alert('Is this regular expression ' + regexp + ' found in this string ' + string + '?\n\n' + regexp.test(string) + '\n\n' + 'Match and captures: ' + regexp.exec(string));

如果您需要匹配货币格式:

var string = '$1..00',
    regexp = /\$\d*(\.\.+)(?:\d\d)+/;

alert('Is this regular expression ' + regexp + ' found in this string ' + string + '?\n\n' + regexp.test(string) + '\n\n' + 'Match and captures: ' + regexp.exec(string));

但是我要提醒你,正则表达式并不适用于比较两个字符串之间的差异;它们用于定义与给定字符串匹配的模式。

因此,虽然这可能直接回答了如何找到“多个点”的模式,但对于“查找两个字符串之间的差异”是无用的。

StackOverflow标签wiki为RegEx提供了出色的概述和基本参考。请参见:https://stackoverflow.com/tags/regex/info


1
问题是关于比较两个字符串,而不仅仅是删除一个字符串。 - Lorenz Meyer
@LorenzMeyer 请看我之前的解释:“但是我要提醒你,正则表达式并不适用于比较两个字符串之间的差异;它们用于定义匹配给定字符串的模式。因此,虽然这可能直接回答了如何找到“多个点”的模式,但对于“查找两个字符串之间的差异”是无用的。” - gfullam
@LorenzMeyer 还请注意我之前在上面对问题的评论,值得注意的是,在问题的多次修改过程中,强调了针对“多个点”模式的正则表达式解决方案。后来,该问题因不清楚而被暂停。 - gfullam
@LorenzMeyer 最后,请参阅何时应该投反对票?。其中指导我们“每当您遇到一个极其草率、没有付出努力的帖子,或者一个明显且可能危险错误的答案时,请使用您的反对票。”考虑到这是一个善意的努力,为OP不清楚的问题的特定部分提供一个可行的解决方案,并附有清晰的解释,我很惊讶您认为它是极其草率、没有付出努力和可能危险错误的。 - gfullam
@gfullam 我尝试为它投票,但我没有足够的声誉 :) 然而,我的问题一直是使用正则表达式查找两个字符串之间的区别——标题中写着。我给出的第一个示例是关于 str1="$1.00" 而 str2="$1..00"。所以我认为这是混淆了。找到双点很简单,但我真正感兴趣的是从 day 1 开始如何在 $1..0 内部替换 $1.00,以便只剩下一个点。我还因为提问而被人踩了 —— 我并不是很在意 :) 而且我知道你正在尽力帮助我。谢谢! - techguy2000

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接