2017-05-07 1 views
0

Ich habe ein Regex-Muster, das perfekt in Python und verschiedenen anderen Sprachen funktioniert, aber nicht die Unterübereinstimmungen für meine Implementierung in einem VBScript regex (die Engine von denen ist scheinbar fast identisch mit JavaScript). Das Muster in Frage lautet wie folgt:Verstehen der Unterschiede in VBScript/Javascript Regex zum Lösen von SubMatch Problem

"Sincerely,[\s\n]+([\w\.]+)\s+(\w+)\s+(.+)[\s\n]+(\d+\s.+)[\s\n]+(.+)" 

Ein Beispiel Testfall ist wie folgt:

email received 3/30/17: 

Dear Sir, 

Hello 

Sincerely, 

Mr. Robert Thomas 
1104 Madison Avenue 
New York, NY 10021 


email received 3/30/17: 

Dear Sir, 

Hello 

Sincerely, 

Ms. Angela Carraway 
402 Arlington Drive 
Concord, MA 01742 

Ziel ist es für eine globale regex, dass Extrakte 5 Untergruppen aus diesem Beispiel Match nach einem variablen Schlüsselwort was hier ist "Mit freundlichen Grüßen". Die Untergruppen sollten Ms. (1. Untergruppe), Angela (zweite Untergruppe), Carraway (dritte Untergruppe), 402 Arlington Drive (vierte Untergruppe), Concord, MA 01742 (fünfte Untergruppe) sein. In Python passt es perfekt zu den 5 Gruppen in einem Regex-Tester, aber für VBScript (die JavaScript-Engine) stimmt es mit der gesamten Zeichenfolge überein, aber ohne Untergruppen. Wenn ich also die Unterübereinstimmungen in einem Excel-VBA-Makro anrufe, um in eine Zelle zu schreiben, bekomme ich den gesamten Text in ein Paar Zellen zerlegt. Was mache ich falsch? Gibt es einen Charakter, den ich vermisse, der die Erfassung von Untergruppen deaktiviert? Wenn ja, was ist der entscheidende Unterschied zwischen diesen beiden Engines, damit ich das in Zukunft vermeiden kann und wie könnte man dieses Muster in diesem Testfall beheben? Ich habe versucht, über die Unterschiede online zu lesen, aber alles gesagt scheint nur kleine Unterschiede zu sein, die das Problem verursachen sollte, das ich habe. Jede Hilfe würde sehr geschätzt werden, weil ich den Unterschied/das Problem nicht isolieren kann. Vielen Dank!

Edit: Im Folgenden ist der VBA-Code, der die Regex verwendet:

Sub regex() 
    Dim docxinput As String 
    Dim keyword As Variant 
    Dim patterninput As Variant 
    Dim pattern As String 
    Dim regex As New RegExp 

    docxinput = Application.GetOpenFilename(Title:="Step #1: Enter Word Document Input File Name") 
     Dim wrdApp As Word.Application 
     Dim wrdDoc As Word.Document 
     Dim strInput As String 

     Set wrdApp = CreateObject("Word.Application") 
     wrdApp.Visible = False 

     Set wrdDoc = wrdApp.Documents.Open(docxinput) 
     strInput = wrdDoc.Range.Text 

     Debug.Print (strInput) 
     wrdDoc.Close 0 
     Set wrdDoc = Nothing 
     wrdApp.Quit 
     Set wrdApp = Nothing 

    pattern = "Sincerely,[\s\n]+([\w\.]+)\s+(\w+)\s+(.+)[\s\n]+(\d+\s.+)[\s\n]+(.+)" 

    Dim objMatches As MatchCollection 

    With regex 
     .Global = True 
     .MultiLine = True 
     .IgnoreCase = False 
     .pattern = pattern 
    End With 

    Set objMatches = regex.Execute(strInput) 
    Dim row As Variant 

    Dim SubMatches As Variant 
    row = 2 
    For Each SubMatches In objMatches 
     Cells(row, 1).Value = objMatches(0).SubMatches(0) 
     Cells(row, 2).Value = objMatches(0).SubMatches(1) 
     Cells(row, 3).Value = objMatches(0).SubMatches(2) 
     Cells(row, 4).Value = objMatches(0).SubMatches(3) 
     Cells(row, 5).Value = objMatches(0).SubMatches(4) 
     row = row + 1 
    Next 
End Sub 

Dies ist ein Bild der Ergebnisse. Wie Sie sehen können, funktionieren die ersten beiden Untergruppen, aber dann läuft die Regex (oder zumindest denke ich) in Gruppierungsfehler und wirft fast den anderen Inhalt in die nächste Spalte. Es bewegt sich dann auf die vierte Spalte und läuft dort auch in Fehler. Ist dies ein Problem beim Iterieren des Codes oder beim Regex selbst? Ich habe versucht, den Code zu beheben, und kann keine Gründe finden, warum er den Text nicht richtig aufbrechen kann, außer dass die Regex fehlerhaft ist. Irgendwelche Gedanken?

Das Bild: Screenshot of VBA Regex Issue

+0

Konnten Sie den VBA-Code, den Sie verwenden, den regex ausführen und die submatches abrufen? –

+0

@RichHolton Ich habe Änderungen am ursprünglichen Post vorgenommen, der den Code und weitere Kommentare zusammen mit einem Bild der Ergebnisse zeigt, die ich beim Ausführen der VBA erhalte. Irgendwelche Gedanken? –

+0

Ich vermute, dass Ihr Text etwas anderes als trennt einige der Zeilen, so dass die dritte Gruppe (. *) Zu viel erfasst, was dann den Rest auswirft. Können Sie nachsehen? –

Antwort

1

Ihre regex mit VBA ohne Probleme laufen sollte ... (getestet here)

die gewünschte Gruppe erhalten in vba mal hier vorbeischauen how-to-use-regular-expressions-regex-in-microsoft-excel-both-in-cell-and-loops.

Edit: Für die folgende Eingabe:

email received 3/30/17: 

Dear Sir, 

Hello 

Sincerely, 

Mr. Robert Thomas 
1104 Madison Avenue 
New York, NY 10021 


email received 3/30/17: 

Dear Sir, 

Hello 

Sincerely, 

Ms. Angela Carraway 
402 Arlington Drive 
Concord, MA 01742 

, die im Inneren der Zelle gesetzt wurde A1

und den VBA-Code:

(beachten Sie, dass ich Ihre ändern for each Schleife - so dass dies für mehrere Übereinstimmungen funktionieren würde

Sub myregex() 
    Dim keyword As Variant 
    Dim patterninput As Variant 
    Dim pattern As String 
    Dim regex As New RegExp 

    Set Myrange = ActiveSheet.Range("A1:A1") 
    For Each C In Myrange 
    strInput = C.Value 
    strPattern = "Sincerely,[\s\n]+([\w\.]+)\s+(\w+)\s+(.+)[\s\n]+(\d+\s.+)[\s\n]+(.+)" 

    With regex 
       .Global = True 
       .MultiLine = True 
       .IgnoreCase = False 
       .pattern = strPattern 
      End With 
      If regex.Test(strInput) Then 
       Set objMatches = regex.Execute(strInput) 
       row = 2 
       For Each SubMatches In objMatches 
       Cells(row, 1).Value = objMatches(row - 2).SubMatches(0) 
       Cells(row, 2).Value = objMatches(row - 2).SubMatches(1) 
       Cells(row, 3).Value = objMatches(row - 2).SubMatches(2) 
       Cells(row, 4).Value = objMatches(row - 2).SubMatches(3) 
       Cells(row, 5).Value = objMatches(row - 2).SubMatches(4) 
       row = row + 1 
       Next 
      Else 
       C.Offset(0, 1) = "(Not matched)" 
      End If 

    Next 
End Sub 

bekam ich folgendes Ergebnis:

 A  B  C   D     E 
    2 Mr. Robert Thomas  1104 Madison Avenue New York, NY 10021 
    3 Ms. Angela Carraway 402 Arlington Drive Concord, MA 01742 

Fazit: Alles funktioniert wie erwartet.

+0

Ich habe diesen Tester auch ausprobiert und er liefert alles als eine Übereinstimmung ohne Untergruppen. Ist das normal? Ich brauche die 5 erfassten Untergruppen innerhalb dieser Gruppe, wenn das Sinn macht. Ich habe auch meinen ursprünglichen Beitrag redigiert, um mehr Detail des Problems zu zeigen, das ich mit dem habe, was ich das Regexmuster vermuthe. –

+0

@ J.Squillaro Also, in diesem Tester (mein erster Link), wenn Sie 'Split-Listen'-Registerkarte wählen, werden Sie Ihre 5 Gruppen dort sehen. Wie man jede Gruppe in vba bekommt - schau dir meinen zweiten Link an. – Plirkee

+0

@ J.Squillaro Ihre 'vba' Skript funktionierte gut für mich in meiner Excel (natürlich nach einigen Adaptionen - ich nicht Word-Dokument verwendet haben, aber eine Excel-Zelle mit einem String' Sehr geehrter Herr, Hallo Mit freundlichen Grüßen, Herr Robert Thomas 1104 Madison Avenue New York, NY 10021' - jedoch Regex Teil arbeitete - Excel 2010, vb Skript reguläre Ausdrücke 5.5) – Plirkee