str.split(someString).join(someOtherString)和replace函数是否等价?(涉及IT技术)

3
我知道例如"This is a test".split("i").join("j")可以将每个i替换为j。 我想知道分割和连接的过程是否与使用正则表达式替换完全等效,或者是否存在任何角落情况,其中对于给定字符串str1str2str3,我们有
str1.split(str2).join(str3) != str1.replace(/str2/g,str3)

编辑:为了澄清,str1.replace(/str2/g,str3) 指的是一个假设的 str1.replaceAll(str2,str3),它将所有出现的 str2 替换为 str3

我不知道,是吗?似乎测试你的假设比在这里发问要容易得多。 - Brian Driscoll
@BrianDriscoll 测试边界情况并不是一件容易的事情。 - Reut Sharabani
@ReutSharabani 我没有说这很琐碎,但我也不认为这很难。当与正则表达式替换进行比较时,很容易看出split()。join()会产生不同/意外的结果。 - Brian Driscoll
1
你不能在 .split().join() 中使用捕获组。 - Felix Kling
@FelixKling 我猜 OP 是在谈论替换非常简单的字符串,即不使用任何正则表达式功能。否则答案显然是“否”。但从技术上讲,你可以在 split 中使用捕获组,但它会有所不同(尝试 "foo".split(/(o)/).join('o'))。 - p.s.w.g
@p.s.w.g:是的,我指的是替换部分。 “我假设OP正在谈论替换非常简单的字符串,即不使用任何正则表达式功能。” 可能吧 :) 我假设 str2 也可以是一个正则表达式。也许不行(因为标题还说“someString”)。 - Felix Kling
3个回答

2
不,它们不是等价的。这里有一个边界情况...
使用空字符串分割将返回原始字符串中每个字符组成的数组:
"foo".split('') --> ["f", "o", "o"]

你可能认为一个空的正则表达式 (RegExp('', 'g') 或者 /(?:)/) 会有同样的效果,特别是如果你使用 split 进行测试:

"foo".split(/(?:)/g) --> ["f", "o", "o"]

然而,在replace方法中,它的工作方式有些不同。因为它匹配字符串中的每个零宽度位置,包括第一个字符之前和最后一个字符之后的零宽度位置:
"foo".replace(/(?:)/g, '-') --> "-f-o-o-"

这是因为split方法在某种意义上从第一个字符“开始”,并在最后一个字符“停止”,而replace方法允许在第一个字符之前“开始”并在最后一个字符之后“停止”。因此,任何匹配字符串开头或结尾的正则表达式都会表现出不同的行为。

var testCases = [/(?:)/g, /^/g, /$/g, /\b/g, /\w*/g];
$.each(testCases, function(i, r) {
    $("#t").append(
      $("<tr>").append(
        $("<td>").text(r.toString()),
        $("<td>").text("foo bar".split(r).join('-')),
        $("<td>").text("foo bar".replace(r, '-'))
      )
    );
  });
* { font-family:monospace; }
table { border-collapse: collapse }
td,th { border:1px solid #999; padding: 3px; }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table id="t">
  <tr>
    <th>RegExp</th>
    <th>str.split(r).join('-')</th>
    <th>str.replace(r, '-')</th>
  </tr>
</table>


0

不用走得太远就能看出split().join()replace()的区别。考虑这样一种情况,你想要将字符串中所有人称代词“me”替换为“myself”。split().join()会替换所有字母序列“me”的出现,而不考虑使用情况,因此字符串“I need some time for me”将变成“I need somyself timyself for myself”。

然而,通过适当的正则表达式,你可以捕获并替换仅有的单词“me”,这样你的结果将是“I need some time for myself”。


1
这是有限制的,即传递给.split的值必须是一个字符串,而不是正则表达式。因为以下代码可以正常工作:"I need some time for me".split(/\bme\b/).join('myself') - Felix Kling

0

简而言之:不行。

你的代码相当于假设性的 string.replaceAll(str,repl),但不是 string.replace(str,repl)

问题在于 string.replace("str","bystr") 只替换第一次出现的 "str"。但是你的代码替换了所有出现的 "str"。


2
我认为OP已经意识到了这一点——注意问题中有一个g标志。我认为OP的意思是,“假设的string.replaceAll(str, repl)是否完全等同于假设的string.replace(RegExp(RegExp.escape(str), "g"), repl)?” - p.s.w.g
@p.s.w.g 这取决于另一个假设的 ECMA 规范中如何定义 hypothetical replaceAll 方法。对我来说,它应该非常接近那个规范。 - c-smile
@p.s.w.g 是的,我的问题基于一个假设的 replaceAll - Ms. Corlib

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