为什么line2
只替换一半出现的次数?
Dim line1 As String = "AAA|BBB|CCC|CCC|CCC|CCC|EEE|FFF"
Dim line2 As String = "AAA|BBB|CCC|CCC|CCC|CCC|EEE|FFF"
Dim line3 As String = "AAA|BBB|CCC|CCC|CCC|CCC|EEE|FFF"
line1 = line1.Replace("CCC", "")
line2 = line2.Replace("|CCC|", "||")
line3 = line3.Replace("CCC|", "|")
结果:
line1 = "AAA|BBB|||||EEE|FFF" -- OK, but fails when element is "..|ZZZCCCZZZ|.."
line2 = "AAA|BBB||CCC||CCC|EEE|FFF" -- Not OK
line3 = "AAA|BBB|||||EEE|FFF" -- OK, but fails similar to Line1 edge-case for "..|ZZZCCC|.."
我尝试过使用RegEx,但得到了类似的结果。
下面真的没有比这更好的方法吗?
Do While line1.Contains("|CCC|")
line1 = line1.Replace("|CCC|", "||")
Loop
答案 0 :(得分:9)
找到第一个令牌后,它会在该令牌之后开始寻找 next 一个。因此它找到|CCC|
,替换它,然后继续,它看到的第一件事是CCC|
,它不匹配。它不预先扫描字符串,寻找要替换的标记。
像这样考虑:
给定AAA|BBB|CCC|CCC|CCC|CCC|EEE|FFF
运行到AAA|BBB|CCC|
HOLD IT |CCC|
,让我们开始构建我们的字符串:
AAA|BBB
+ ||
(我们的替代品)
现在让我们继续前进,我们现在可以使用CCC|CCC|CCC|EEE|FFF
。
找到了CCC|CCC|
HOLD IT |CCC|
,让我们继续添加到我们的字符串中:
AAA|BBB||CCC
+ ||
(我们的替代品)
现在让我们继续,我们现在有CCC|CCC|EEE|FFF
等等等等。
编辑:考虑MSDN上描述返回值的条目:
一个字符串,它等同于当前字符串,除了all oldValue的实例将替换为newValue。
一个 可以读取它预期它预先扫描字符串并找到所有匹配的内容。我没有在MSDN文档中看到任何描述此角落案例的内容。也许这应该添加到MSDN文档中。
答案 1 :(得分:3)
您可以解析值,过滤掉您不想要的值并将它们重新连接在一起,而不是使用正则表达式或string.Replace
。
line1 = string.Join("|", line1.Split("|").Select(s => s == "CCC" ? "" : s).ToArray());
抱歉,我不知道VB等价物。
答案 2 :(得分:1)
对于将来的任何人,我都添加了一种扩展方法来克服框架中的这种限制:
<System.Runtime.CompilerServices.Extension()>
Public Function ReplaceAll(ByVal original As String, ByVal oldValue As String, ByVal newValue As String) As String
If newValue.Contains(oldValue) Then
Throw New ArgumentException("New value can't be a subset of OldValue as infinite replacements can occur.", newValue)
End If
Dim maxIterations As Integer = original.Length \ oldValue.Length
While maxIterations > 0 AndAlso original.Contains(oldValue)
original = original.Replace(oldValue, newValue)
maxIterations -= 1
End While
Return original
End Function
答案 3 :(得分:0)
对于这种情况,我可能会使用regular expression replace和look-around。
考虑这个例子:
Regex.Replace("FCCCF|CCC|CCC|", "((?<=[|])CCC(?=[|]))", "")
// ->
"FCCCF|||"
这将始终匹配正确的次数,并且不会出现任何无限递归问题。它需要修改适当的正则表达式并更改替换数据。
然而,请注意克里斯的评论:
Regex.Replace("FCCCF|CCC|CCC||CCC|", "((?<=[|])CCC(?=[|]))", "")
// -> only 5 pipes: verify this is correct per the intended semantics
"FCCCF|||||"