我试图从字符串中提取括号括起来的最后一个组。 字符串可以是以下变体之一:
String ' Extracted sub
-------------- ' -------------
Some (text) ' text
Some text ' "" or "Some text"
Some (text) (here) ' here
Some (text) (is situated (here)) ' is situated (here)
Some text (is situated (here)) ' is situated (here)
Some (text) (is (situated (here))) ' is (situated (here))
我需要最后一个右括号和相应的左括号之间的substring
。
我测试了Split
,Mid
,InStr
和InStrRev
的所有变种......
答案 0 :(得分:2)
不确定你尝试了什么,但这个想法是(希望它的写作逻辑性):
)
(
)
)
时增加#3,满足(
时减少#3,#3变为零时停止。"ERROR: UNMATCHED BRACKETS!"
以下代码在Excel中测试(在评论中更新样本YowE3K)
Option Explicit
Function LastOutmostBracketText(ByVal InputText As String) As String
Dim lRightMostCloseBracket As Long, CloseBracketCount As Long
Dim lRightMostOpenBracket As Long
Dim sTmp As String
Dim sOutput As String
If InStr(1, InputText, "(", vbTextCompare) > 0 And InStr(1, InputText, ")", vbTextCompare) > 0 Then
' Find the Last Close Bracket
lRightMostCloseBracket = InStrRev(InputText, ")")
' Find the Last Open Bracket
lRightMostOpenBracket = InStrRev(InputText, "(")
If (lRightMostCloseBracket - lRightMostOpenBracket) > 1 Then
' Count how many Close brackets within the last Open and last Close bracket
sTmp = Mid(InputText, lRightMostOpenBracket, lRightMostCloseBracket - lRightMostOpenBracket)
CloseBracketCount = Len(sTmp) - Len(Replace(sTmp, ")", ""))
' Find the matching Open Bracket by looking at previous characters
Do Until CloseBracketCount = 0 Or lRightMostOpenBracket = 1
If lRightMostOpenBracket > 0 Then lRightMostOpenBracket = lRightMostOpenBracket - 1
sTmp = Mid(InputText, lRightMostOpenBracket, 1)
Select Case sTmp
Case "(": CloseBracketCount = CloseBracketCount - 1
Case ")": CloseBracketCount = CloseBracketCount + 1
End Select
Loop
If lRightMostOpenBracket = 1 And CloseBracketCount > 0 Then
sOutput = "ERROR: UNMATCHED BRACKETS!" & vbCrLf & InputText
Else
sOutput = Mid(InputText, lRightMostOpenBracket + 1, lRightMostCloseBracket - 1 - lRightMostOpenBracket)
End If
End If
End If
LastOutmostBracketText = sOutput
End Function
答案 1 :(得分:1)
我怀疑正则表达式确实可以做得更好但这是我知道如何编写的代码(现在包含了@YowE3K的“错误案例”和他更清醒 - 尽管他自称疲倦 - 理解括号内的括号应该是什么处理的): -
Private Function LastBracket(ByVal Txt As String) As String
' 08 Jan 2018
Dim Fun As String
Dim x As Integer, y As Integer
Dim n As Integer, m As Integer
For n = 0 To Len(Txt) - 1
Fun = Fun & Mid(Txt, Len(Txt) - n, 1)
Next n
n = InStr(Fun, ")") ' remove trailing text
If n Then
Fun = Mid(Fun, n)
Else
Exit Function ' no bracket found
End If
Do
n = InStr(m + 1, Fun, "(")
If n Then
Txt = Left(Fun, n)
m = n
x = Len(Txt) - Len(Replace(Txt, "(", ""))
y = Len(Txt) - Len(Replace(Txt, ")", ""))
Else
Exit Function ' paired bracket not found
End If
Loop Until x = y
Fun = Txt
Txt = ""
For n = 1 To Len(Fun) - 2
Txt = Txt & Mid(Fun, Len(Fun) - n, 1)
Next n
LastBracket = Txt
End Function
如果没有括号内的文本或括号为空,它将返回一个空字符串。以下是我跑的测试。
Private Sub TestUnpack()
Debug.Print "Result = "; LastBracket("Some; Text")
Debug.Print "Result = "; LastBracket("Some; Text()")
Debug.Print "Result = "; LastBracket("Some(Text)")
Debug.Print "Result = "; LastBracket("Some(Text)(here)")
Debug.Print "Result = "; LastBracket("Some (text) (might be (here))")
Debug.Print "Result = "; LastBracket("Some (text) (might be (situated (here)))")
Debug.Print "Result = "; LastBracket("Some (text) (might be (situated (here))) not here")
Debug.Print "Result = "; LastBracket("abc ((def) ghi (jkl) (mno (pqr)) stu) vwx")
End Sub
答案 2 :(得分:0)
使用CSet的方法略有不同(但大致相同):
Sub test()
Dim i As Integer
Dim str As String
Dim rng As Range
Dim l As Integer
For i = 1 To ActiveDocument.Sentences.Count
Set rng = ActiveDocument.Paragraphs.Item(i).Range
rng.End = rng.End - 1
l = Len(rng.Text)
rng.Collapse wdCollapseEnd
Do
rng.MoveStartUntil cset:="(", Count:=-l
rng.Start = rng.Start - 1
str = rng.Text
Loop While Len(Replace(str, "(", vbNullString)) <> Len(Replace(str, ")", vbNullString))
Debug.Print str
str = vbNullString
Next i
End Sub
哦,我太懒了去除外括号,但我希望这不应该太有问题; - )