RegEx负前瞻性替换不包括起始和结束模式



我在VBA中使用RegEx,并试图替换开始和结束垂直管道中的任何非垂直管道的字符。

换句话说,我的文本看起来是这样的:

++++|+++This|Is|An|Example++|+++++

我只想替换出现在第一个管道之后和最后一个管道之前的非管道字符。

因此,使用";a";作为替换字符,例如:

++++|aaaaa|aa|aaaaaa|++++

我尝试过一种负先行(RegEx的VBA实现不支持先行(,虽然它可以将最后一个管道之后的字符排除在替换之外,但第一个管道之前的字符仍然会被替换:

(?!^ *|)[^|](?! *$)

aaa|aaaaa|aa|AAAAAA|+++

我显然没有正确理解负前瞻,因为我似乎无法将出现在第一个管道之前的字符从匹配中排除。

有人能帮我做这个吗?

如果数据遵循模式(总是至少有两个垂直管道(,这里有一个可选的第一部分:

(^[^|]*|)?[^|](?=[^|]*|)

请在regex101中查看此演示(在演示中使用n以避免跳过行(-替换为$1a

直到第一根管道被捕获到第一组$1并插入以进行替换的零件
先行检查在每个[^|](否定类(之后是否还有另一个|管道在前面。

这是一种变通方法,但您可以使用一个快速循环来遍历字符串,并使用一个简单得多的Regex模式来替换每个部分,而不是使用一个可能在VBA中不起作用的复杂Regex模式。

Sub Example()
Const InputString As String = "++++|+++This|Is|An|Example++|++++"
Debug.Print DoTheThing(InputString)
'Output: ++++|aaaaaaa|aa|aa|aaaaaaaaa|++++
End Sub
Function DoTheThing(InputString As String) As String
Dim Pieces() As String
Pieces = Split(InputString, "|")

Dim Regex As Object
Set Regex = CreateObject("VBScript.RegExp")
Regex.Global = True
Regex.Pattern = "."

If UBound(Pieces) > 1 Then
Dim i As Long
For i = 1 To UBound(Pieces) - 1
Pieces(i) = Regex.Replace(Pieces(i), "a")
Next
End If

DoTheThing = Join(Pieces, "|")
End Function

或者你甚至可以完全避免使用Regex对象:

Sub Example()
Const InputString As String = "++++|+++This|Is|An|Example++|++++"
Debug.Print DoTheThing(InputString)
'Output: ++++|aaaaaaa|aa|aa|aaaaaaaaa|++++
End Sub
Function DoTheThing(InputString As String) As String
Dim Pieces() As String
Pieces = Split(InputString, "|")

If UBound(Pieces) > 1 Then
Dim i As Long
For i = 1 To UBound(Pieces) - 1
Pieces(i) = String(Len(Pieces(i)), "a")
Next
End If

DoTheThing = Join(Pieces, "|")
End Function

(?!^ *|)[^|](?! *$)正则表达式与匹配

  • (?!^ *|)-一个不立即后跟零个或多个空格的位置,然后是一个|字符
  • [^|]-除|字符之外的任何字符
  • (?! *$)-紧挨着右边,应该没有可选的空格,然后是字符串的末尾

我建议使用另一种方法:匹配并捕获需要保留的内容,只匹配需要替换的内容。

参见VBA代码:

Dim pattern As regExp, m As Object
Dim text As String, result As String, repl As String, offset As Long
text = "++++|+++This|Is|An|Example++|++++"
repl = "a"
offset = 0
Set pattern = New regExp
With pattern
.pattern = "(^++|||++$)|[^|]"
.Global = True
End With
result = text
For Each m In pattern.Execute(text)
If Len(m.SubMatches(0)) = 0 Then ' If Group 1 matched, replace with "a"
result = Left(result, m.FirstIndex + offset) & repl & Mid(result, m.FirstIndex + m.Length + 1 + offset)
offset = offset + Len(repl) - m.Length
End If
Next

输出:++++|aaaaaaa|aa|aa|aaaaaaaaa|++++

(^++|||++$)|[^|]正则表达式与匹配

  • (^++|||++$)-组1:一个或多个+字符,然后在字符串开始处有一个|,或者一个|,然后一个或更多个+字符,直到字符串结束
  • |-或
  • [^|]-除|字符之外的任何字符

以下是我在python中解决问题的方法。作为一个团队,我向后看,向前看。我创建了一个捕获组,查找+(0或更多(、单词字符(1或更多(和空格(0或更大(,然后使用?重复捕获组:

data="++++|+++This is bb|Is|An|Example++|++++"
replace_with="a"
matches=re.findall(r'(?<=|)(?:+*w++*s*)+(?=|)', data)
for match in matches:
print(match)
data=data.replace(match,replace_with*len(match))
print(data)

输出:

++++|aaaaaaaaaaaaa|aa|aa|aaaaaaaaa|++++

最新更新