14 Stimmen

Wie extrahiere ich eine Teilzeichenkette in Klammern mit einem Regex-Muster?

Dies ist wahrscheinlich ein einfaches Problem, aber leider konnte ich nicht die gewünschten Ergebnisse erzielen...

Sagen wir, ich habe die folgende Zeile:

"Wouldn't It Be Nice" (B. Wilson/Asher/Love)

Nach diesem Muster muss ich suchen:

" (<any string>)

Zum Abrufen:

B. Wilson/Asher/Love

Ich habe etwas ausprobiert wie "" (([^))]*)) aber es scheint nicht zu funktionieren. Außerdem würde ich gerne Match.Submatches(0) das könnte die Sache etwas verkomplizieren, weil es auf Klammern angewiesen ist...

25voto

alan Punkte 4472

bearbeiten : Nach der Prüfung Ihres Dokuments besteht das Problem darin, dass vor den Klammern keine regulären Leerzeichen, sondern umgebrochene Leerzeichen stehen. Diese Regex sollte also funktionieren: ""[ \xA0]*\(([^)]+)\)

""       'quote (twice to escape)
[ \xA0]* 'zero or more non-breaking (\xA0) or a regular spaces
\(       'left parenthesis
(        'open capturing group
[^)]+    'anything not a right parenthesis
)        'close capturing group
\)       'right parenthesis

In einer Funktion:

Public Function GetStringInParens(search_str As String)
Dim regEx As New VBScript_RegExp_55.RegExp
Dim matches
    GetStringInParens = ""
    regEx.Pattern = """[ \xA0]*\(([^)]+)\)"
    regEx.Global = True
    If regEx.test(search_str) Then
        Set matches = regEx.Execute(search_str)
        GetStringInParens = matches(0).SubMatches(0)
    End If
End Function

4voto

Das ist nicht unbedingt eine Antwort auf Ihre Frage, aber manchmal sind die guten alten String-Funktionen für so einfache Dinge weniger verwirrend und prägnanter als Regex.

Function BetweenParentheses(s As String) As String
    BetweenParentheses = Mid(s, InStr(s, "(") + 1, _
        InStr(s, ")") - InStr(s, "(") - 1)
End Function

Verwendung:

Debug.Print BetweenParentheses("""Wouldn't It Be Nice"" (B. Wilson/Asher/Love)")
'B. Wilson/Asher/Love

EDITAR @alan weist darauf hin, dass dadurch der Inhalt der Klammern im Liedtitel falsch zugeordnet wird. Dies kann mit einer kleinen Änderung leicht umgangen werden:

Function BetweenParentheses(s As String) As String
    Dim iEndQuote As Long
    Dim iLeftParenthesis As Long
    Dim iRightParenthesis As Long

    iEndQuote = InStrRev(s, """")
    iLeftParenthesis = InStr(iEndQuote, s, "(")
    iRightParenthesis = InStr(iEndQuote, s, ")")

    If iLeftParenthesis <> 0 And iRightParenthesis <> 0 Then
        BetweenParentheses = Mid(s, iLeftParenthesis + 1, _
            iRightParenthesis - iLeftParenthesis - 1)
    End If
End Function

Verwendung:

Debug.Print BetweenParentheses("""Wouldn't It Be Nice"" (B. Wilson/Asher/Love)")
'B. Wilson/Asher/Love
Debug.Print BetweenParentheses("""Don't talk (yell)""")
' returns empty string

Natürlich ist das weniger prägnant als früher!

3voto

buckley Punkte 12756

Dies ist eine schöne Regex

".*\(([^)]*)

In VBA/VBScript:

Dim myRegExp, ResultString, myMatches, myMatch As Match
Dim myRegExp As RegExp
Set myRegExp = New RegExp
myRegExp.Pattern = """.*\(([^)]*)"
Set myMatches = myRegExp.Execute(SubjectString)
If myMatches.Count >= 1 Then
    Set myMatch = myMatches(0)
    If myMatch.SubMatches.Count >= 3 Then
        ResultString = myMatch.SubMatches(3-1)
    Else
        ResultString = ""
    End If
Else
    ResultString = ""
End If

Dies entspricht

Put Your Head on My Shoulder

in

"Don't Talk (Put Your Head on My Shoulder)"  

Aktualisierung 1

Ich habe die Regex auf Ihre Doc-Datei losgelassen und sie stimmt wie gewünscht überein. Ich bin ziemlich sicher, dass die Regex in Ordnung ist. Ich kenne mich mit VBA/VBScript nicht so gut aus, aber ich vermute, dass genau da der Fehler liegt.

Wenn Sie die Regex weiter diskutieren wollen, ist das in Ordnung für mich. Ich bin nicht erpicht darauf, mich in diese VBscript-API zu vertiefen, die sehr geheimnisvoll aussieht.

Angesichts der neuen Eingabe wird die Regex wie folgt angepasst

".*".*\(([^)]*)

Damit es nicht fälschlicherweise mit (Put Your Head on My Shoulder) übereinstimmt, das innerhalb der Anführungszeichen steht.

enter image description here

2voto

JimmyPena Punkte 8590

Diese Funktion hat bei Ihrer Beispielzeichenkette funktioniert:

Function GetArtist(songMeta As String) As String
  Dim artist As String
  ' split string by ")" and take last portion
  artist = Split(songMeta, "(")(UBound(Split(songMeta, "(")))
  ' remove closing parenthesis
  artist = Replace(artist, ")", "")
End Function

Ex:

Sub Test()

  Dim songMeta As String

  songMeta = """Wouldn't It Be Nice"" (B. Wilson/Asher/Love)"

  Debug.Print GetArtist(songMeta)

End Sub

druckt "B. Wilson/Asher/Love" in das Sofort-Fenster.

Es löst auch das Problem alan erwähnt . Ex:

Sub Test()

  Dim songMeta As String

  songMeta = """Wouldn't (It Be) Nice"" (B. Wilson/Asher/Love)"

  Debug.Print GetArtist(songMeta)

End Sub

druckt auch "B. Wilson/Asher/Love" in das Sofortfenster. Es sei denn, die Künstlernamen stehen ebenfalls in Klammern.

1voto

Hackoo Punkte 16852

Diese andere Regex wurde mit einem vbscript getestet (?:\()(.*)(?:\)) Demo hier


Data = """Wouldn't It Be Nice"" (B. Wilson/Asher/Love)"
wscript.echo Extract(Data)
'---------------------------------------------------------------
Function Extract(Data)
Dim strPattern,oRegExp,Matches
strPattern = "(?:\()(.*)(?:\))"
Set oRegExp = New RegExp
oRegExp.IgnoreCase = True 
oRegExp.Pattern = strPattern
set Matches = oRegExp.Execute(Data) 
If Matches.Count > 0 Then Extract = Matches(0).SubMatches(0)
End Function
'---------------------------------------------------------------

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X