RegExp: String ausschließen

  • Hallo, wie kann man mit StringRegExp einen String "nicht finden" / ausschließen ?

    Bsp.: "test" soll nicht gefunden werden:
    [^test] findet alles außer t, e, s, t
    (^test) gibt es nicht
    Kombinationen wie [^(test)] oder ([^t][^e][^s][^t]) gehen auch nicht....

    Blicke ich einfach nicht durch oder ist das wirklich so kompliziert ? Kann da Jemand helfen ?
    besseres Beispiel:


    Gefunden werden soll von <item> bis </item>, aber nur das mit "test2" im <main> tag !
    Das Pattern '<item>(?s).*?<main>test2</main>(?s).*?</item>' findet aber vom 1. bis zum Ende des 2. <item> tag.

    CODe auf dem Bildschirm....

    3 Mal editiert, zuletzt von powerbass4 (17. März 2014 um 18:16)

  • nee muss schon RegExp sein; das ist ja nur ein Teil des pattern...

    StringRegExp('"der test eins", "was anderes"', '".*?"') findet beides, es soll aber nur "was anderes" gefunden werden.

    CODe auf dem Bildschirm....

    • Offizieller Beitrag

    Ich denke mal, du hast folgendes vor:
    1. du hast einen beliebigen Suchbegriff (kommt in einem main-Tag vor)
    2. nun willst du die zugehörigen item-Tags dafür auslesen (title, text)
    3. alle anderen item bleiben unberücksichtigt

    Ist das korrekt?
    Dein Pattern müsste dann nichts ausschliessen, sondern NUR den item-/item Bereich mit deinem Suchbegriff einschliessen. So wird ein Schuh draus.

    Edit:
    Hier mal ein Pattern, das dieses Ergebnis bringt:
    \<item\>\s*\<title>([^<]+)\</title\>\s*\<main\>(test2)\</main>\s*\<text\>([^<]+)\</text\>\s*\</item\>

    Ergebnis:
    $a[0] = title
    $a[1] = main = Suchbegriff (blau im Pattern)
    $a[0] = text

  • [autoit]

    $sString = FileRead(@ScriptDir & '\tmp.xml')
    $sFind = 'test2'
    $sPattern = '(?s)(?U)(?:<item>.*?<title>(.*?)</title>.*?(?<=<main>' & $sFind & '</main>).*?<text>(.*?)</text>.*?</item>)'

    [/autoit][autoit][/autoit][autoit]

    $aResult = StringRegExp($sString, $sPattern,1,1)
    for $element in $aResult
    ConsoleWrite($element & @LF)
    Next

    [/autoit]

    Edit: Ups ... BugFix hat schneller editiert :)

  • Erstmal Danke.....aber da gibt es ein Problem; die einzigen Konstanten sind die <item> und <main> tags ! (alles was noch im <item> tag steht ist unbekannt)

    Die einfachste Lösung wäre einen <item> tag zwischen dem öffnendem <item> und den (beiden) <main> tags auszuschließen.
    '<item>alles außer <item> tags<main>test2</main>(?s).*?</item>'
    Warum kan man ein Set ausschließen [^<item>] aber keine Gruppe (^<item>) ?

    Ich habe es auch schon mit dem "darf davor/danach (nicht) stehen" versucht. Eigentlich ganz einfach, aber die RegExp Engine scheint das nicht zu können....

    CODe auf dem Bildschirm....

    • Offizieller Beitrag

    Erstmal Danke.....aber da gibt es ein Problem; die einzigen Konstanten sind die <item> und <main> tags ! (alles was noch im <item> tag steht ist unbekannt)


    Ich verstehe nicht, was du willst.
    Du hast uns ein Muster erstellt, anhand dieses Musters wurde das Pattern erstellt - und das passt auch korrekt. Du legst nur den Inhalt von "main" als Suchbegriff fest, alles andere ist völlig egal, was in den Tags steht.
    Wenn du meinst das funktioniert nicht mit deiner Vorlage, dann zeig doch bitte eine korrekte Vorlage.

    Und deine Fragestellung ist immer wieder falsch. Classes gibt es nicht für Wörter, wäre ja auch widersinnig, da das dann mit RegEx nichts mehr zu tun hat.

    Zitat

    Die einfachste Lösung wäre einen <item> tag zwischen dem öffnendem <item> und den (beiden) <main> tags auszuschließen.

    Ganz und gar nicht, das wäre die komplizierteste aller Varianten.
    Ein Pattern sollte so erstellt werden, dass es effektiv und allgemeingültig ist. Je spezieller, desto komplizierter. ;)

  • ok, nochmal neu und hoffentlich etwas klarer....


    gefunden werden soll:

    XML
    <item>
    	....
    	<main>test2</main>
    	....
    </item>


    (Mit mehr als nur einem RegExp, also mehreren Instanzen, ist das kein Problem.)

    CODe auf dem Bildschirm....

    • Offizieller Beitrag

    Ich interpretiere die Punkte in deinem Bsp. als beliebig viele Inner-Tags, die ebenfalls selektiert werden sollen.

    Das kannst du dann so auslesen:

    [autoit]

    $sSearch = "test2"
    $sPattern = "(<item>\s*(?:<[^>]+>(?:[^<]+)</[^<]+>\s*)*<main>" & $sSearch & "</main>\s*(?:<[^>]+>(?:[^<]+)</[^<]+>\s*)*</item>)"
    $sString = _
    '<item>' & @CRLF & _
    ' <tagA>111111</tagA>' & @CRLF & _
    ' <tagB>222222</tagB>' & @CRLF & _
    ' <main>test1</main>' & @CRLF & _
    ' <tagC>333333</tagC>' & @CRLF & _
    ' <tagD>444444</tagD>' & @CRLF & _
    '</item>' & @CRLF & _
    '<item>' & @CRLF & _
    ' <tagA>111111</tagA>' & @CRLF & _
    ' <tagB>222222</tagB>' & @CRLF & _
    ' <main>test2</main>' & @CRLF & _
    ' <tagC>333333</tagC>' & @CRLF & _
    ' <tagD>444444</tagD>' & @CRLF & _
    '</item>' & @CRLF & _
    '<item>' & @CRLF & _
    ' <tagA>111111</tagA>' & @CRLF & _
    ' <tagB>222222</tagB>' & @CRLF & _
    ' <main>test3</main>' & @CRLF & _
    ' <tagC>333333</tagC>' & @CRLF & _
    ' <tagD>444444</tagD>' & @CRLF & _
    ' <tagE>555555</tagE>' & @CRLF & _
    '</item>' & @CRLF

    [/autoit][autoit][/autoit][autoit]

    $aMatch = StringRegExp($sString, $sPattern, 3)
    If IsArray($aMatch) Then
    For $i = 0 To UBound($aMatch) -1
    ConsoleWrite($aMatch[$i] & @LF)
    Next
    EndIf

    [/autoit]

    Gefunden wird:

    Code
    <item>
    	<tagA>111111</tagA>
    	<tagB>222222</tagB>
    	<main>test2</main>
    	<tagC>333333</tagC>
    	<tagD>444444</tagD>
    </item>

    Wenn du Hilfe bei einem Pattern benötigst, ist es unerlässlich die Rahmenbedingungen 100% exakt anzugeben. Damit das Pattern greift müssen alle Textvarianten bei der Erstellung bekannt sein.
    Hättest du von Anbeginn gesagt, dass du anhand eines bekannten Wertes in dem main-Tag allen Inhalt im umfassenden item-Tag auslesen möchtest, wäre die Kuh sofort vom Eis gewesen.
    Dadurch, dass du aber ständig darauf beharrt hast einen Lösungsansatz mit Ausschluss zu verfolgen, hast du nur Verwirrung gestiftet. :rolleyes:
    Mach dir aber nichts draus, den Punkt haben wir alle schon erlebt. ;) Da rennt man wie vernarrt einem Lösungsweg hinterher und sieht nichts links und rechts. Darum ist es immer von Vorteil, so viel wie möglich vom Problem zu schildern. Dann kann hier oft ein effektiverer Weg vorgeschlagen werden. :thumbup:

  • Kannst du mir diesen Teil (?:<[^>]+>(?:[^<]+)</[^<]+>\s*) des Pattern bitte noch erläutern. :rolleyes:

    Das ist einfach nur ein beliebiges XML Tag bzw. eine Ansammlung von Tags, d.h. z.B. <irgendwas>a = b</irgendwas>. genauere Erklärung

    @all Auch wenn sich das Thema jetzt geklärt hat wüsste ich trotzdem gerne ob und wie man einzelne Strings von der Suche ausschließen kann, vielleicht weiß das ja jemand.

  • Schritt für Schritt:

    Code
    (?: - Gruppe, welche nicht in die Ergebnisse übernommen wird
    <[^>]+> - Ein "<", gefolgt von einem oder mehr beliebigen Zeichen außer ">" bis hin zum nächsten ">"
    (?: - Noch eine Gruppe ohne Ergebnisübernahme
    [^<]+ - Ein oder mehrere beliebige Zeichen außer "<"
    ) - Ende einer Gruppe (Z. 3)
    </[^<]+> - "</" gefolgt von einem oder mehreren beliebigen Zeichen, außer "<", gefolgt von einem ">"
    \s* - Ein beliebiges Whitespace-Zeichen, also ein nicht sichtbares Zeichen (beliebige Anzahl)
    ) - Ende einer Gruppe (Z. 1)

    Ich hoffe, ich habe so detailliert keinen Fehler gemacht. ^^