http://lmgtfy.com/?q=GDI%2B+Tutorial+Tut+Baustelle
Ist aber noch in Arbeit.
http://lmgtfy.com/?q=GDI%2B+Tutorial+Tut+Baustelle
Ist aber noch in Arbeit.
Naja ein Obfus ist das jedenfalls nicht wirklich. Allerdings sind das deine ersten AutoIt Schritte, weswegen ich es wiederum gut finde.
Alles in allem
PS: Ich verstehe unter einem Obfuscator eher sowas https://autoit.de/index.php?page…6941#post146941
Ich empfehle dafür den OnEvent Mode.
http://translation.autoit.de/onlinehilfe/gu…OnEventMode.htm
Ich wollte noch erwähnen, dass es ein weiteres, weitaus besseres WinHTTP Tut gibt.
Einfach dem Link von Schnitzel folgen. In der gleichen Section in dem entsprechenden Forum gibt es ein weiteres Tutorial.
"WinHTTP einstieg zu [...]"
Nein. Gibts nicht. _FFClick kann kein Drag&Drop simulieren.
OT: Auch einer. Wer will mit mir wetten?
Und ich hätte noc hdie hier zu bieten:
HotKeySet("{NUMPADADD}", "_HKS")
HotKeySet("{NUMPADSUB}", "_HKS")
HotKeySet("{END}", "_HKS")
HotKeySet("{NUMPADMULT}", "_HKS")
While 1
Sleep(1000)
WEnd
Func _HKS()
Local $sKey, $hWnd = WinGetHandle("iTunes")
If @HotKeyPressed = "{END}" Then Exit
If @HotKeyPressed = "{NUMPADADD}" Then $sKey = "{RIGHT}"
If @HotKeyPressed = "{NUMPADSUB}" Then $sKey = "{LEFT}"
If @HotKeyPressed = "{NUMPADMULT}" Then $sKey = "{SPACE}"
If Not IsHWnd($hWnd) Then Return ConsoleWrite("Konnte iTunes Handle nicht erlangen" & @CRLF)
ControlSend($hWnd, "", "Button10", $sKey)
ConsoleWrite("+> Send! " & $sKey & @CRLF)
Sleep(500)
EndFunc ;==>_HKS
Probier mal das:
#include <SendMessage.au3>
#include <WindowsConstants.au3>
HotKeySet("{NUMPADADD}", "_HKS")
HotKeySet("{NUMPADSUB}", "_HKS")
HotKeySet("{END}", "_HKS")
HotKeySet("{NUMPADMULT}", "_HKS")
While 1
Sleep(1000)
WEnd
Func _HKS()
Local $sKey, $hWnd = WinGetHandle("iTunes")
If @HotKeyPressed = "{END}" Then Exit
If @HotKeyPressed = "{NUMPADADD}" Then $sKey = "{RIGHT}"
If @HotKeyPressed = "{NUMPADSUB}" Then $sKey = "{LEFT}"
If @HotKeyPressed = "{NUMPADMULT}" Then $sKey = "{SPACE}"
If Not IsHWnd($hWnd) Then Return ConsoleWrite("Konnte iTunes Handle nicht erlangen" & @CRLF)
_SendMessage($hWnd, $WM_SETFOCUS,1)
ControlSend($hWnd, "", "Static26", $sKey)
ConsoleWrite("+> Send! " & $sKey & @CRLF)
_SendMessage($hWnd, $WM_KILLFOCUS,1)
Sleep(500)
EndFunc ;==>_HKS
Zu 1. Nein, nicht auf herkömmliche Weise. Eigentlich garnicht. Du könntest ein Input machen, welches du drüber legtst auf nem extra GUI. Dann WinSetTrans 1. Wenn der User ins (fast) unsichtbare Edit schreibt, kannst du den Text im Lable ändern. (Label unterstützen Transparente hintergrundfarben)
2.
$hGUI = GUICreate("")
GUISetBkColor(0)
_GuiRoundCorners($hGUI,0,0,90,90)
GUISetState()
While 1
$nMsg = GUIGetMsg()
Switch $nMsg
Case -3
Exit
EndSwitch
WEnd
Func _GuiRoundCorners($hWnd, $x1, $y1, $x3, $y3)
Local $pos, $ret, $ret2
$pos = WinGetPos($hWnd)
$ret = DllCall('gdi32.dll', 'long', 'CreateRoundRectRgn', 'long', $x1, 'long', $y1, 'long', $pos[2], 'long', $pos[3], 'long', $x3, 'long', $y3)
If $ret[0] Then
$ret2 = DllCall('user32.dll', 'long', 'SetWindowRgn', 'hwnd', $hWnd, 'long', $ret[0], 'int', 1)
If $ret2[0] Then
Return 1
Else
Return 0
EndIf
Else
Return 0
EndIf
EndFunc ;==>_GuiRoundCorners
Und wieder ein Bot... warum wird denn hier noch Support gegeben? Im letzen PixelSearch Thread hat man uns auch gut verarscht.
Ich bin für ein automatisiertes schließen von Posts, in denen Send, PixelSearch oder ImageSearch vorkommen.
Danke für das Lob alle zusammen.
Edit: Ich sehe gerade, du bist ja auch Erleuchtet. Spart viel Strom.
Das liegt an der Flamme, die auf meiner Tüte brennt
RegExp ist nicht unbedingt von Vorteil wenn man das so machen will wie Matthias. Ich empfehle das deswegen so:
$hGUI = GUICreate("", 120, 60)
$hInput = GUICtrlCreateInput("", 10, 10, 100, 20)
$hButton = GUICtrlCreateButton("OK", 10, 35, 100, 20)
GUISetState()
While 1
$nMsg = GUIGetMsg()
Switch $nMsg
Case -3
Exit
Case $hButton
GUICtrlSetData($hInput, _Crypt(GUICtrlRead($hInput)))
EndSwitch
WEnd
Func _Crypt($sString)
Local $sRet, $aSplit = StringSplit($sString, "", 3)
Local $aSnR[1000][2] = [ _
["a", "$50765&"],["b", "$147447&"],["c", "$472868&"],["d", "$311020&"],["e", "$450806&"], _
["f", "$254710&"],["g", "$279031&"],["h", "$65555&"],["i", "$65939&"],["j", "$459710&"], _
["k", "$485879&"],["l", "$54162&"],["m", "$404054&"],["n", "$175431&"],["o", "$124132&"], _
["p", "$482736&"],["q", "$295972&"],["r", "$71975&"],["s", "$128644&"],["t", "$224984&"], _
["u", "$448694&"],["v", "$267864&"],["w", "$174224&"],["x", "$293531&"],["y", "$55901&"], _
["z", "$50028&"],[" ", "$176767&"],["A", "$112235&"],["B", "$222317&"],["C", "$467908&"], _
["D", "$208577&"],["E", "$320536&"],["F", "$314906&"],["G", "$429374&"],["H", "$313276&"], _
["I", "$417985&"],["J", "$469185&"],["K", "$314778&"],["L", "$89812&"],["M", "$497053&"], _
["N", "$326433&"],["O", "$15248&"],["P", "$256020&"],["Q", "$12367&"],["R", "$497765&"], _
["S", "$6625&"],["T", "$93807&"],["U", "$246036&"],["V", "$47442&"],["W", "$237122&"], _
["X", "$263641&"],["Y", "$115352&"],["Z", "$47249&"],["0", "$4435&"],["1", "$346552&"], _
["2", "$444489&"],["3", "$182044&"],["4", "$211491&"],["5", "$73835&"],["6", "$222954&"], _
["7", "$127472&"],["8", "$219928&"],["9", "$221144&"],[",", "$152487&"],[".", "$4967&"], _
["/", "$408694&"],["\", "$291959&"],[":", "$390063&"],["-", "$426713&"],["_", "$332383&"], _
["?", "$238865&"],["!", "$344814&"],["#", "$420542&"],["&", "$401614&"],["=", "$37433&"] _
]
For $sElement In $aSplit
For $i = 0 To UBound($aSnR) - 1
If $aSnR[$i][0] == $sElement Then $sRet &= $aSnR[$i][1]
Next
Next
Return $sRet
EndFunc ;==>_Crypt
ZitatAuf Wunsch von Pee poste ich mein StringRegExp Tutorial nun auch hier. Ich bitte zu beachten, dass die Stellen, welche Beispiele oder Aufgaben beinhalten, welche sich auf Browsergame Quelltexte beziehen, werden die nächsten Tagen abgeändert.
Inhaltsverzeichnis:
1. Vorwort
2. Was ist ein Regulärer Ausdruck?
3. Unser erster RegExp
4. Komplexere RegExp
5. Quantifizer, Fangende- und nicht Fangende Gruppierungen
6. Konditionales RegExp
7. Assertionen, Backreference
Fortsetzung folgt...)
1. Vorwort
Hallo und herzlich Willkommen zu meinem aller ersten Tutorial. Ich möchte euch in diesem Tutorial die Regulären Ausdrücke näher bringen. Aber nicht nur das: Ich möchte euch genauso den Spaß am "RegExen" vermitteln, und hoffe natürlich alles genauestens erklären zu können. Solltet ihr etwas nicht verstehen, oder noch offene Fragen haben, dann möchte ich euch bitten, natürlich jederzeit im Thread zu posten, um mich auf evtl. Schwachstellen des Tutorials aufmerksam zu machen oder um selbstverständlich Antworten auf offene Fragen zu bekommen.
Mein Dank gilt an dieser Stelle einerseits den Machern der Webseite https://autoit.de/www.regenechsen.de, deren Workshop mich seinerzeit die Regulären Ausdrücke ( nachfolgend RegEx oder RegExp genannt ) gelehrt hat, aber auch der Firma JGSoft, ohne deren RegExBuddy(Ein Leistungsstarkes RegEx-Tool mit Syntaxhighlighting uvm.) ich wohl oft verzweifelt wäre. Genug der vielen Worte. Ich hoffe ihr seid bereit, denn wir heben in Kürze ab
2. RegExp?!
2.1Was ist ein Regulärer Ausruck?
Zitat von WikipediaIn der Informatik ist ein regulärer Ausdruck (engl. regular expression, Abk. RegExp oder Regex) eine Zeichenkette, die der Beschreibung von Mengen beziehungsweise Untermengen von Zeichenketten mit Hilfe bestimmter syntaktischer Regeln dient.
Das sagt zumindest Wikipedia. Ich werde mein bestes geben, dieses Kauderwelsch für euch zu entschlüsseln. Zuerst solltet ihr wissen: Ihr habt wahrscheinlich alle schonmal einen RegExp benutzt. Zum Beispiel bei der Suche nach mp3-Dateien auf euren Computern: Man öffnet die Windows-Suche und sucht nach
*.mp3
Gefunden werden alle Dateien, deren Name auf ".mp3" endet. Das Sternchen steht für eine beliebige Anzahl unbekannter Zeichen.
Möchten wir alle Dateien finden, deren Namen ein "S" beinhaltet, worauf 2 Zeichen später ein "G" folgt und auf .txt endet, schreiben wir
*s??g.txt
Hier werden also ? und * als Platzhalter verwendet. Diese "RegExe" sind aber eher infantil; und keinesfalls so mächtig wie ein richtiger Regulärer Ausdruck - Denn in eben jenem sind die Zeichen nicht nur Platzhalter.
Ein RegExp ist also ein Suchmuster. Zum Beispiel ist es leicht, alle Worte in einem Text zu finden, die auf E beginnen, und mit n enden. Zu meinem Lieblingsbeispiel komme ich gleich.
2.2 Was bringt mir ein RegExp überhaupt?!
Wir nehmen mal folgenden Quelltextausschnitt. WIr wollen den Lagerstand herausfinden.
<td><img src="img/x.gif" class="r1" alt="Holz" title="Holz"></td>
<td id="l4" title="600">132411/240000</td>
<td><img src="img/x.gif" class="r2" alt="Lehm" title="Lehm"></td>
<td id="l3" title="600">168007/240000</td>
<td><img src="img/x.gif" class="r3" alt="Eisen" title="Eisen"></td>
<td id="l2" title="750">32743/240000</td>
<td><img src="img/x.gif" class="r4" alt="Getreide" title="Getreide"></td>
<td id="l1" title="79">78451/240000</td>
Mit _Stringbetween müsste man jetzt nach allem zwischen "> und </td> suchen. Ich kann mir aber vorstellen, dass es da massig Ergebnisse geben wird.
Das heißt wir müssten uns erst mit Stringbefehlen ein Stück aus dem Quellcode zurechtschneiden, hier mal trimmen, da mal etwas ersetzen, nur um dann am Ende den Lagerstand herauszufinden. Das sind wieder 10 Zeilen unnötiger Code. Per RegExp macht man einfach folgendes:
$aResult = StringRegExp($HTML,"l[1-4][^>]+>(\d+\/\d+)",3)
_Arraydisplay($aResult)
Ich glaube das sollte als Erklärung reichen
3. Unser erster RegExp
3.1 Vorbereitung
Um das Tutorial effektiv zu gestalten, möchte ich mich mit euch auf eine Darstellungsform einigen. Ich werde Die RegExe IMMER in [ Code ]-Tags hüllen, damit man Sie besser erkennt.
Ich möchte euch bitten, den RegExBuddy zu installieren, damit ihr die RegExe testen, und Aufgaben im Tutorial leichter verwirklichen könnt. Die Demo Version könnt ihr hier herunterladen.
Der RegExpbuddy ist für den RegExer, wie der Pinsel für den Maler. Wie der Taktstock für einen Dirigenten, oder der Kugelschreiber für den Rapper - Ein Werkzeug um Kunst zu erstellen! (Na gut, beim Rapper müsst ihr mir nicht zwingend zustimmen :D). Der RegExbuddy hat vieles was nützlich ist, und noch viel mehr, was man schon garnicht mehr braucht. Hauptsächlich interessant sind allerdings die gute Verlässlichkeit, sowie das Syntaxhighlighting. Mal ganz zu schweigen von der Fehlererkennung (zb bei falscher Klammersetzung). Was er alles kann werdet ihr selbst herausfinden müssen. Ich kann euch jedoch nur raten, euch das Ding anzuschaffen.
Hier habe ich mal die wichtigsten Bedienelemente im RegExbuddy hervorgehoben:
(sorry, man kann scheinbar keine bilder in spoiler-tags einfügen)
[Blockierte Grafik: http://i48.tinypic.com/xbjmef.jpg]
ACHTUNG: Schaltet die RegExp Engine (Im Bild auf "Perl") auf "PCRE". Das ist die RegExp Engine, die in AutoIt verwendet wird. (Weiß ich auch erst seit ca. 1 Stunde.)
3.2 Das erste Suchmuster
Unser erster RegEx wird simpel, denn bekanntlich muss jeder einmal klein anfangen.
Ja, das ist schon ein Regulärer Ausdruck! Gesucht wird nun nach der Zeichenkette "grund oder folge". Und die RegEx-Maschine ist stur und erbarmungslos! Sie sucht genau das was man ihr aufträgt; Gefunden wird nicht nur bei
sondern auch bei
3.3 Case Sensitivity in AutoIt
Ganz wichtig (und Grund dafür, dass RegExe bei mir früher nicht immer Funktioniert haben), ist, dass AutoIt-RegExp immer Case-sensitive arbeiten. Soll heißen: Groß- und Kleinschreibung werden unterschieden. Um dieses Verhalten zu unterdrücken, gibt es verschiedene Wege. Ich werde aber, da wir gerade erst mit dem Tutorial begonnen haben, nur eine erläutern:
(?i) sorgt dafür, dass ab dem Punkt, wo es im RegExp steht, Groß- und Kleinschreibung ignoriert wird. (?-i) Macht das genaue Gegenteil
BEISPIEL:
"SciTE ist die Standard AutoIt-IDE"
Lassen wir nun den folgenden RegExp auf diesen String los, werden wir keinen Treffer landen:
Machen wir das ganze aber mit unserem gerade gelernten (?i), so finden wir das Wort "SciTE":
Ihr solltet deswegen im RegExpBuddy die Buttons "Case insensitive" zu deaktiveren, und "^$ match at linebreaks" zu aktivieren. Zu letzterem komm ich später.
3.3 Literale Suche nach Metazeichen
Mit einem Regex lässt sich alles suchen: Alphanumerische (a-Z, 0-9), Hexadezimale, Binäre Zeichen uvm.
Eine kleine Ausnahme bilden allerdings die Metazeichen einer RegEx-Maschine. Diesen sind nämlich besondere Aufgaben innerhalb eines RegEx zugewiesen.
Zitat* + ? . ( ) [ ] { } \ / | ^ $
Metazeichen haben bestimmte Funktionen innerhalb eines RegExp. Als Beispiel wären da ^ und $, welche Zeilenanfang und -ende repräsentieren. Oder *,+,? die als Wiederholungszeichen dienen. (Dazu kommen wir in Kapitel 5)
Einige Experten werden nun aufschreien oder vom Stuhl kippen. Ja, nicht alle dieser Zeichen sind tatsächlich Metazeichen. (Zum Beispiel sind die geschweiften Klammern 'eigentlich' keine Metazeichen). Aber nehmen wir mal an, es wäre so.
Ich habe all diese Zeichen hier aufgelistet, weil man sie "escapen" muss um sie zu finden. Möchte man also nach einem Fragezeichen suchen, so schreibt man \?.
Sucht man nach einer schließenden geschweiften Klammer, so schreibt man \}. Sucht man nach einem Backslash, so schreibt man \\.
Eine andere Möglichkeit ist das benutzen von
Alles was zwischen \Q und \E steht, wird auch genauso gesucht. Die "Funktionen" der Metazeichen werden also nicht aktiv.
Allerdings ist das normale escapen i.d.R. einfacher, schneller und überischtlicher.
Achtung: Wenn ihr mal nicht wisst, ob ihr etwas escapen sollt oder nicht, dann escaped lieber einmal mehr als zu wenig.
Ein
wird zu keinem Fehler führen
3.4 Der Punkt unter der Lupe.
Unser erstes Metazeichen, welches wir uns anschauen ist der Punkt "."
Ein Punkt steht für ein beliebiges, unbekanntes Zeichen. Ein Punkt kann für jedes Zeichen stehen. Standartmäßig aber nicht für Zeilenumbrüche. Das kann allerdings auch mit einem speziellen RegExp-Flag (wie schon bei der Groß- Kleinschreibung) geändert werden.
findet "Maier" und "Meier" , aber nicht "Meyer". Außerdem findet es "Meierling" bis zum "r".
findet "Hand", "Herd", "Hardrock" aber nicht "Hausdach" oder "Haende"
Später im Tutorial zeige ich euch, wie man u.a. nach mehreren unbekannten Zeichen suchen kann, ohne deren Anzahl explizit angeben zu müssen.
3.5 Zeichenklassen
Langsam geht es los! In diesem Abschnitt lernt ihr etwas über Zeichenklassen. Zeichenklassen sind eine "Bündelung von Zeichen", besser erklären kann ich es in einem Beispiel.
sucht nach einer Zahl von 0-9. \d\d sucht folglich nach 2 aufeinanderfolgenden Zahlen.
sucht nach einem Alphanumerischen Zeichen, sprich einem Klein oder Großbuchstaben, einer Zahl oder einem Unterstrich "_"
Damit lassen sich schon schwierigere RegExe zusammenbauen:
Dieser RegExp sucht nach 2 Alphanumerischen Zeichen gefolgt von einem Komma, einem Leerzeichen, zwei Ziffern und einem Punkt, gefolgt von einem Leerzeichen und 3 alphanumerischen Zeichen.
Gefunden wird zB:
"Mo, 12. Jan", "Sa, 03. Mai" und "Fr, 13. Dezember" aber nicht "Do, 4 Apr" oder "Mi 25. Jul"
Eine sehr elegante Methode um eigene Zeichenklassen zu erstellen, sind eckige Klammern "[]".
Mit diesen eckigen klammern wird EIN ZEICHEN gesucht, egal wie viele in den klammern stehen.
sucht nach einer Ziffer, gefolgt von einem Großbuchstaben(!) von A-G.
Gefunden wird also "9B", "7D", "3F" aber nicht "6X" oder "5yA".
Anstatt jedes mal [ABCDEFG] schreiben zu müssen, eröffnet uns RegExp die Möglichkeit einfach
[A-G] zu schreiben. Das ist kürzer und sieht gleich noch viel cooler aus!
Begeben wir uns mal an einen etwas schwereren RegExp:
findet alle Datumsangaben im Format "TT.MM." Komplett falsche Daten wie zb "66.29." werden hier bereits ausgeschlossen.
Der ein oder andere hat vielleicht schon gemerkt: Ein Datum wie zb "39.19." wird trotzdem gefunden. Verbessern wir den RegExp später, wenn wir etwas mehr Erfahrung im Bereich der logischen Operatoren gesammelt haben, okey?
Die so erstellten Zeichenklassen lassen sich ohne Probleme umdrehen:
sucht nach allen Zeichen, die keine Großbuchstaben von A-G sind.
Achtung: Das Zirkumflex "^" hat eine vollkommen andere Bedeutung, wenn es außerhalb der eckigen Klammern steht. Das solltet ihr euch merken. Aber dazu später mehr.
3.6 Überblick über Kapitel 3
Wir haben einfache RegExe und Metazeichen kennengelernt.
3.7 Aufgaben
Was suchen die folgenden RegExe:
Zwei Ziffern gefolgt von einem Doppelpunkt und zwei weiteren Ziffern. Dies trifft auf die Darstellung einer Uhrzeit zu. (Bsp: 14:52)
Diesen RegExp hatten wir so ähnlich schon bei Abschnitt 3.5. Gesucht werden 3 alphanumerische Zeichen, gefolgt von einem Komma und einem Leerzeichen, gefolgt von 2 Ziffern, einem Leerzeichen und 3 weiteren alphanumerischen Zeichen. Darauf folgen noch ein Leerzeichen und 4 Ziffern. Auch das sieht nach einem Datum aus, aber in der anglo-amerikanischen Schreibweise: Tue, 19 Feb 2002. Leider ist dieses Regex nicht optimal: es erkennt nur Daten mit zweistelligen Tageszahlen. Wir werden etwas später sehen, wie man das Regex modifiziert, um sowohl einstellige als auch zweistellige Tageszahlen zu finden.
Gesucht wird das Wort "Re" gefolgt von einem Leerzeichen, einer öffnenden eckigen Klammer, dann eine Ziffer von 0-9 und abschließend eine schließende eckige Klammer.
4. Komplexere RegExp
Das war ja kinderleicht oder? Genau! Aber leider waren viele RegExe die ich eben gezeigt habe sehr unflexibel. Wäre das schon die volle Macht der RegExp gewesen, so hätte es sich nicht gelohnt ein Tutorial dafür zu schreiben. RegExe können noch mehr. Noch viel viel mehr! Und ich zeige euch jetzt auch WAS sie alles können!
4.1 Wortgrenzen und die Verwendung von RegExp in AutoIt
Erinnert ihr euch an unser erstes Beispiel?
Fahre ich in den Abgrund oder folge ich der Straße?
Grund oder Folge der Armut?
Wenn wir nun mit der sog. Wortgrenzen-Zeichenklasse \b arbeiten, erhalten wir
Dieses "Pattern", so wie der RegExp-String in Autoit genannt wird, findet nur noch "Grund oder Folge der Armut", aber nicht mehr "Fahre ich in den Abgrund oder folge ich der Straße?"
Da ich noch garnicht erwähnt habe, wie RegExp in AutoIt angewand wird, werde ich das nun nachholen. Das eben gezeigte Beispiel wird nun mal in AutoIt eingebaut.
[autoit]
#include <Array.au3>
$sString = _
"Grund oder Folge der Armut?" & @CRLF & _
"Fahre ich in den Abgrund oder folge ich der Straße?"
$aResult = StringRegExp($sString,"(?i)\bgrund oder folge\b",3)
_ArrayDisplay($aResult,"StringRegExp Results")
Ihr könnt ja mal testweise die Wortgrenzen \b entfernen
Die Parameter sollten verständlich sein. $sString ist der Ausgangsstring, in dem wir suchen. Danach folgt unser RegExp-Pattern. Der letzte Parameter gibt an, in welcher Form der Array $aResult zurückgegeben werden soll. In 99% der Fällen reicht Flag 3 vollkommen aus. (Ich habe glaub ich selbst noch nie ein anderes Flag benutzt.)
Hier allerdings mal ein kleines Script, nur um die verschiedenen Rückgabeformen zu verdeutlichen:
#include <Array.au3>
$sString = _
'<td><img src="img/x.gif" class="r1" alt="Holz" title="Holz"></td>' & @CRLF & _
'<td id="l4" title="600">132411/240000</td>' & @CRLF & _
'<td><img src="img/x.gif" class="r2" alt="Lehm" title="Lehm"></td>' & @CRLF & _
'<td id="l3" title="600">168007/240000</td>' & @CRLF & _
'<td><img src="img/x.gif" class="r3" alt="Eisen" title="Eisen"></td>' & @CRLF & _
'<td id="l2" title="750">32743/240000</td>' & @CRLF & _
'<td><img src="img/x.gif" class="r4" alt="Getreide" title="Getreide"></td>' & @CRLF & _
'<td id="l1" title="79">78451/240000</td>'
$aFlag1 = StringRegExp($sString, "l[1-4][^>]+>(\d+\/\d+)", 1)
$aFlag2 = StringRegExp($sString, "l[1-4][^>]+>(\d+\/\d+)", 2)
$aFlag3 = StringRegExp($sString, "l[1-4][^>]+>(\d+\/\d+)", 3)
$aFlag4 = StringRegExp($sString, "l[1-4][^>]+>(\d+\/\d+)", 4)
MsgBox(0, "", "Flag 0 gibt 1 (matched) oder 0 (no match) zurück.")
MsgBox(0, "Flag 0", StringRegExp($sString, "l[1-4][^>]+>(\d+\/\d+)"))
MsgBox(0, "", "Flag 1 zeigt das erste Match (nur Subpatterns)")
_ArrayDisplay($aFlag1, "Flag 1")
MsgBox(0, "", "Flag 2 zeigt das erste Match (Full Match + Subpatterns)")
_ArrayDisplay($aFlag2, "Flag 2")
MsgBox(0, "", "Flag 3 zeigt alle Matches (nur Subpatterns)")
_ArrayDisplay($aFlag3, "Flag 3")
MsgBox(0, "", "Flag 4 gibt einen Array voller Arrays zurück.")
_ArrayDisplay($aFlag4, "Flag 4")
MsgBox(0, "", "Die einzelnen Arrays beinhalten Full Match + Subpatterns." & @CRLF & _
"Leider kann man Arrays in Arrays nicht direkt ansprechen" & @CRLF & _
"(ohne sie zwischenzuspeichern), deswegen benutze ich statt Flag 4 immer Flag 3." & @CRLF & _
"Hier mal alle Arrays in $aFlag4:")
For $i = 0 To UBound($aFlag4) - 1
$aDummy = $aFlag4[$i]
_ArrayDisplay($aDummy, "$aFlag4[" & $i & "]")
Next
4.2 Zeilen- oder Zeichenkettengrenzen
Manchmal will man, dass ein bestimmter Text explizit am Zeilenanfang, oder vielleicht sogar am absoluten Stringanfang gefunden wird. Dafür gibt es bestimmte Metazeichen, von denen wir eines schon im letzen Kapitel kennengelernt haben. ^ und $ stehen für Zeilenanfang und -ende.
Findet "AutoIt ist total cool!", aber nicht "Ich finde AutoIt toll!".
findet "Mein liebstes Hobby ist AutoIt.", aber nicht "Sag mir: Was ist besser als AutoIt?"
Das gleiche gibt es statt für Zeilenanfang und -ende auch als Metazeichen für den kompletten String. \A steht für den Stringanfang, \z steht für das Stringende. Eine Besonderheit gibt es hier auch: \Z ist eine Mischung aus \z und $. Denn es steht für Stingende ODER Zeilenende.
Diese Metazeichen helfen uns auch, unseren RegExp zu beschleunigen! Stellen wir uns die Zeichenkette "AutoIt ist sehr praktisch" vor. Wir wenden nun diesen RegExp darauf an:
Die RegExp Maschine überprüft ob das erste Zeichen der Zeilenanfang ist -> Wahr
Nun wird geprüft ob das zweite Zeichen ein R ist -> Falsch.
Die RegExp Maschine bricht ab. Hätten wir ^ nicht benutzt, so würde die RegEx Maschine nun den kompletten String durchgehen, und nach "RegExp" suchen, nur um festzustellen, dass der String nicht vorhanden ist.
4.3 Whitespaces
Nachdem wir eben Wort-, Zeilen,- und Stringgrenzen kennengelernt haben, kommen wir zu einer anderen sehr häufig genutzten Zeichenklasse. Den Whitespaces. Mit \s wird ein Whitespace gesucht - Also ein Zeichen, welches eine weiße Fläche hinterlässt. Dazu gehören @CRLF, @CR, @LF, @TAB, und das Leerzeichen.
#include <Array.au3>
$sString = "Grund"&@TAB&"oder"&@CR&"Folge"&@CRLF&"der Armut?" & @CRLF & _
"Fahre ich in den Abgrund oder folge ich der Straße?"
$aResult = StringRegExp($sString,"(?i)grund\soder\sfolge",3)
;~ _ArrayDisplay($aResult,"StringRegExp Results") ; Da _ArrayDisplay keine Tabs & co darstellen kann,
; Zeige ich euch die Ergebnisse in einer MsgBox.
MsgBox(0,"",$aResult[0])
MsgBox(0,"",$aResult[1])
4.4 Logischer Operator: OR
Also logische Operatoren bezeichnet man in der Informatik u.a AND und OR.
OR, also einen Oder-Operator gibt es in RegExp auch: Mehrer oder-Blöcke werden durch eine sog. Pipe "|" voneinander getrennt. Das geht sowohl außerhalb einer Klammer als auch darin. Zu den Klammern komme ich im Nächsten Kapitel, wenn wir mit Subpatterns arbeiten. Ich hoffe aber dass das Beispiel auch ohne vorherige Erklärung ersichtlich ist.
Ignoriert das "?:" bitte vorerst.
[autoit]#include <Array.au3>
$sString = "Mein Name ist Peter"& @CRLF
$sString &= "Mein Name ist Karl"& @CRLF
$sString &= "Mein Name ist Christian"& @CRLF
$sString &= "Mein Name ist Max"& @CRLF
$sString &= "Mein Name ist Paul"& @CRLF
$sString &= "Mein Name ist Manfred"& @CRLF
$aResult = StringRegExp($sString,"Mein Name ist (?:Karl|Max|Paul)",3)
_ArrayDisplay($aResult)
4.5 Übersicht über Kapitel 4
Wir haben komplexer Patterns, erweiterte Metazeichen und den OR-kennengelernt.
4.6 Aufgaben.
Schreibe ein Pattern, welches alle korrekten Uhrzeiten im Teststring findet.
15:44
12:37
99:73
64:33
00:00
24:00
17:12
(die roten sind falsch!)
Benutze dieses Script als vorlage:
#include <Array.au3>
$sString = _
"15:44" & @CRLF & _
"12:37" & @CRLF & _
"99:73" & @CRLF & _
"64:33" & @CRLF & _
"00:00" & @CRLF & _
"24:00" & @CRLF & _
"17:12" & @CRLF
$aArray = StringRegExp($sString,"",3)
_ArrayDisplay($aArray)
Schreibe einen Pattern, der nach einer Seriennummer sucht. 4 Blocks a 4 Zeichen von A-Z und Zahlen von 0-6, mit Bindestrichen getrennt.
KKJD-4WR6-1562-Z31A
22JE-2XAB-RRY4-U24U
22JE-2XAB-R9Y4-U24U
5PLM-4GHS-2TZ6-1132
99A5-7777-ABCD-9786
(die Roten sind falsche Seriennummern)
Was bedeuten die folgenden Suchmuster?
Das erste Muster sucht nach allen Texten, die einen Zeilenanfang haben oder am Zeilenanfang beginnen. Es werden also alle Strings, sogar der leere String gefunden!
Das zweite Muster sucht nach Zeilen, in denen nur der Buchstabe x steht, direkt nach Zeilenbeginn und am Ende der Zeile.
Und das letzte Muster sucht einfach nach allen Texten, die Zeilenanfang und -ende haben, aber nichts dazwischen. Es werden leere Zeilen gesucht.
5. Quantifizer, Fangende- und nicht Fangende Gruppierungen
In diesem Kapitel fängt der wirklich harte Stoff an. Am besten ihr lest es langsam und sorgfältig durch, und testet so viele der Beispiele im RegexBuddy.
Sobald wir mit dem Kapitel fertig sind, macht ihr es am besten noch einmal.
5.1 Quantifizer
Das ist der Part, an dem RegExe interessant werden, da man nun endlich "richtige" Patterns bauen kann. Ein Quantifizer ist ein Wiederholungszeichen. Es gibt an, wie oft etwas wiederholt werden soll, damit der RegExp erfolgreich ist. Dabei ist es egal, ob der Quantifizer auf Zeichenklassen, einzeilne Buchstaben, Subpatterns (dazu kommen wir im nächsten Abschnitt) oder sonstwas angewandt wird.
Es gibt 3 wichtige Quantifizer: ? + *
Das Malzeichen "*" gibt an, dass etwas beliebig oft, aber auch keinmal gefunden werden soll. Dieser Quantifizer ist gierig.
Moment..., Habe ich da gerade "gierig" gesagt? Ja! Man unterscheidet nämlich zwischen gierig (greedy) und faul (lazy) bei Quantifizern. Aber dazu gleich mehr.
Das Pluszeichen "+" gibt an, dass etwas beliebig oft, mindestens aber ein mal(!) vorkommen soll. Dieser Quantifizer ist gierig.
Das Fragezeichen "?" gibt an, dass etwas einmal, oder keinmal gefunden werden soll. Dieser Quantifizer ist gierig.
Wie schon bei den Zeichenklassen, sind wir aber nicht darauf beschränkt was RegExp uns von Haus aus bietet. WIr können eigene Quantifizer erstellen.
Diese sehen zB. so aus: {1,2}
Rate doch mal was dieser Quantifizer macht!
Genau! Er gibt an, dass die Zeichenklasse, das Subpattern oder sonst was Mindestens 1 mal, höchstens aber 2 mal gefunden werden soll.
Man kann die zweite Zahl auch weglassen. (Das Komma muss aber bleiben) Das bedeutet dann so viel wie "ohne Grenze nach oben". {3,} sucht also mindestens 3 vorkommen, findet es mehr ist das auch i.O. Die oben genannten Quantifizer + * ? sind nur Kurzformen für diese Art der Quantifizierung.
+ = {1,}
* = {0,}
? = {0,1}
Wenn wir das Komma "," auch noch weglassen, dann wird nach einer exakten übereinstimmung gesucht.
Sucht nach allen 4-Stelligen Strings.
Mit diesem Wissen können wir schon mal versuchen unser Seriennummern Pattern aus Kapitel 4 aufzubessern. Das sah ja wirklich elendig lang aus.
KKJD-4WR6-1562-Z31A
22JE-2XAB-RRY4-U24U
22JE-2XAB-R9Y4-U24U
5PLM-4GHS-2TZ6-1132
99A5-7777-ABCD-9786
(die Roten sind falsche Seriennummern)
[A-Z0-6][A-Z0-6][A-Z0-6][A-Z0-6]-[A-Z0-6][A-Z0-6][A-Z0-6][A-Z0-6]-[A-Z0-6][A-Z0-6][A-Z0-6][A-Z0-6]-[A-Z0-6][A-Z0-6][A-Z0-6][A-Z0-6]
Wie müsste man das Pattern umschreiben, damit es zwar immer noch alle Seriennummern findet, aber kürzer und besser aussieht?
Wir haben also 4 Zeichen in jeder Gruppe. Das heißt wir können diesen Rattenschwanz hier:
schonmal durch
ersetzen. Wir suchen nach 4 "Blöcken" a 4 Zeichen gefolgt von einem Bindestrich.
Aber... Moment?! Warum wird denn jetzt nichts gefunden?
Habt ihr den Fehler entdeckt? Richtig! Hinter dem letzten Block folgt ja garkein Bindestrich.
Das heißt wir suchen nur nach 3 Blöcken mit bindestrich, gefolgt von einem ohne Bindestrich.
Das sieht doch schon wesentlich besser aus als unser Pattern von eben, oder?
Alternativ geht auch dieses Pattern:
Allerdings werden hier auch Blöcke ohne Bindestiche gefunden. Also wie verbessern wir das?
Sucht nun nach 4 Blocks a 4 Zeichen von A-Z bzw 0-6, gefolgt von entweder einem Bindestrich, oder dem Zeilenende.
5.1 Gruppierung
Ihr habt es jetzt schon in ein paar Patterns gesehen und von der Mathematik sollte man es auch bereits kennen: Mit Klammern kann man Gruppieren. Das dient nicht nur dem Zweck, dass der Term, oder hier beim Regexen das Pattern hübsch aussieht, sondern man kann explizit angeben, welcher Teil eines Terms (Patterns) zueinander gehört. Das ist beim RegExen praktisch, da man auf die Abschnitte in Klammern ua. Quantifizer benutzen kann. Man kann den OR-Operator sinnvoll nutzen uvm.
Man unterscheided zwischen Fangender Gruppierung und Nicht fangender Gruppierung.
5.1.1 Fangende Gruppierungen aka. Subpatterns.
Grundlegend, wird alles was wir einklammern in sog. Subpatterns gespeichert. Subpattern sind temporäre Variablen, die wir für spätere Zwecke noch verwenden können.
Hier mal ein Beispiel:
#include <Array.au3>
$sString = "SEuBo Email: SEuBo@web.de" & @CRLF
$sString &= "SEuBo Email: Peter@live.de" & @CRLF
$sString &= "Acanis Email: Acanis@gmx.net" & @CRLF
$sString &= "Acanis Email: Coolertyp@googlemail.com" & @CRLF
$aRegExp = StringRegExp($sString,"(\w+) Email: (\1@\w+\.\w+)",3)
_ArrayDisplay($aRegExp)
Wie ihr seht, wird das erste Wort (auf welches " Email: " folgt) in einer temporären Variable gespeichert ( weil eingeklammert )
Diese Variable wird mit \1 abgerufen. Die 1 steht dabei für die Nummer des Subpatterns.
Subpatterns haben außerdem den Vorteil, dass jedes SubPattern in einem eigenen Array Element gespeichert wird. Das hilft uns unter anderem besonders wenn es um Arbeit mit Quelltexten geht.
Hier mal ein Beispiel mit einem etwas fortgeschritteneren RegExp.
#include <Array.au3>
Global $sQuellCode
QuellCode()
$aRes = StringRegExp($sQuellCode,'href="([^"]+).+?>([^<]+)[\W\w]+?cox">\((\d+)[\W\w]+?coy">(\d+)',3)
For $i = 0 to UBound($aRes)-1 Step 4
MsgBox(0,"","Dorfname: "&@TAB&$aRes[$i+1] & @CRLF & _
"Link: "&@TAB&@TAB&$aRes[$i] & @CRLF & _
"X: "&@TAB&@TAB&$aRes[$i+2] & @CRLF & _
"Y: "&@TAB&@TAB&$aRes[$i+3] & @CRLF)
Next
Func QuellCode()
$sQuellCode = ''
$sQuellCode &= '<tr><td class="dot hl">?</td><td class="link"><a href="?newdid=82867">01 ? Panic Room[VO]</a></td><td class="aligned_coords">' & @CRLF
$sQuellCode &= '<div class="cox">(17</div>' & @CRLF
$sQuellCode &= '<div class="pi">|</div>' & @CRLF
$sQuellCode &= '<div class="coy">113)</div></td></tr><tr><td class="dot">?</td><td class="link"><a href="?newdid=89034" accesskey="n">02 ? Das 9er[RK]</a></td><td class="aligned_coords">' & @CRLF
$sQuellCode &= '<div class="cox">(244</div>' & @CRLF
$sQuellCode &= '<div class="pi">|</div>' & @CRLF
$sQuellCode &= '<div class="coy">64)</div></td></tr><tr><td class="dot">?</td><td class="link"><a href="?newdid=92071">03 ? Hilf dem HD[DD]</a></td><td class="aligned_coords">' & @CRLF
$sQuellCode &= '<div class="cox">(244</div>' & @CRLF
$sQuellCode &= '<div class="pi">|</div>' & @CRLF
$sQuellCode &= '<div class="coy">63)</div></td></tr><tr><td class="dot">?</td><td class="link"><a href="?newdid=93854">04 ? Nummer 2[DD]</a></td><td class="aligned_coords">' & @CRLF
$sQuellCode &= '<div class="cox">(242</div>' & @CRLF
$sQuellCode &= '<div class="pi">|</div>' & @CRLF
$sQuellCode &= '<div class="coy">63)</div></td></tr><tr><td class="dot">?</td><td class="link"><a href="?newdid=96194">05 ? Laberbacke[DD]</a></td><td class="aligned_coords">' & @CRLF
$sQuellCode &= '<div class="cox">(240</div>' & @CRLF
$sQuellCode &= '<div class="pi">|</div>' & @CRLF
$sQuellCode &= '<div class="coy">63)</div></td></tr><tr><td class="dot">?</td><td class="link"><a href="?newdid=100593">06 ? Noch n Dorf[DD]</a></td><td class="aligned_coords">' & @CRLF
$sQuellCode &= '<div class="cox">(241</div>' & @CRLF
$sQuellCode &= '<div class="pi">|</div>' & @CRLF
$sQuellCode &= '<div class="coy">63)</div></td></tr><tr><td class="dot">?</td><td class="link"><a href="?newdid=105638">07 ? 0-8-15[DD]</a></td><td class="aligned_coords">' & @CRLF
$sQuellCode &= '<div class="cox">(241</div>' & @CRLF
$sQuellCode &= '<div class="pi">|</div>' & @CRLF
$sQuellCode &= '<div class="coy">64)</div></td></tr><tr><td class="dot">?</td><td class="link"><a href="?newdid=107915">08 ? Notgeil</a></td><td class="aligned_coords">' & @CRLF
$sQuellCode &= '<div class="cox">(244</div>' & @CRLF
$sQuellCode &= '<div class="pi">|</div>' & @CRLF
$sQuellCode &= '<div class="coy">66)</div></td></tr><tr><td class="dot">?</td><td class="link"><a href="?newdid=74485">09 ** FrisBy</a></td><td class="aligned_coords">' & @CRLF
$sQuellCode &= '<div class="cox">(13</div>' & @CRLF
$sQuellCode &= '<div class="pi">|</div>' & @CRLF
$sQuellCode &= '<div class="coy">108)</div></td></tr><tr><td class="dot">?</td><td class="link"><a href="?newdid=111417">10 ? Langeweile</a></td><td class="aligned_coords">' & @CRLF
$sQuellCode &= '<div class="cox">(238</div>' & @CRLF
$sQuellCode &= '<div class="pi">|</div>' & @CRLF
$sQuellCode &= '<div class="coy">69)</div></td></tr><tr><td class="dot">?</td><td class="link"><a href="?newdid=114355">11 ? Monkey Island</a></td><td class="aligned_coords">' & @CRLF
$sQuellCode &= '<div class="cox">(240</div>' & @CRLF
$sQuellCode &= '<div class="pi">|</div>' & @CRLF
$sQuellCode &= '<div class="coy">65)</div></td></tr><tr><td class="dot">?</td><td class="link"><a href="?newdid=114359">12 ? Süchtig</a></td><td class="aligned_coords">' & @CRLF
$sQuellCode &= '<div class="cox">(237</div>' & @CRLF
$sQuellCode &= '<div class="pi">|</div>' & @CRLF
$sQuellCode &= '<div class="coy">68)</div></td></tr><tr><td class="dot">?</td><td class="link"><a href="?newdid=114372">13 ? Schon wieder</a></td><td class="aligned_coords">' & @CRLF
$sQuellCode &= '<div class="cox">(237</div>' & @CRLF
$sQuellCode &= '<div class="pi">|</div>' & @CRLF
$sQuellCode &= '<div class="coy">70)</div></td></tr><tr><td class="dot">?</td><td class="link"><a href="?newdid=114548">14 ? Blood Island</a></td><td class="aligned_coords">' & @CRLF
$sQuellCode &= '<div class="cox">(243</div>' & @CRLF
$sQuellCode &= '<div class="pi">|</div>' & @CRLF
$sQuellCode &= '<div class="coy">66)</div></td></tr><tr><td class="dot">?</td><td class="link"><a href="?newdid=114547">15 ? Enteninsel</a></td><td class="aligned_coords">' & @CRLF
$sQuellCode &= '<div class="cox">(243</div>' & @CRLF
$sQuellCode &= '<div class="pi">|</div>' & @CRLF
EndFunc ;==>QuellCode
5.1.2 Gierige und faule Quantifizer
Jetzt komme ich nochmal auf das Verhalten der Quantifizer zurück. Ich habe ja eben schon angemerkt, dass die Quantifizer "gierig" sind.
Ich nehme jetzt mal das Beispiel aus dem Workshop von Regenechsen.de
Wir wollen ein Regex, das beliebigen Text in Hochkommata findet und als Subpattern ablegt. Wir benutzen den *-Quantifizer, der ja bekanntlich gierig ist.
[autoit]#include <Array.au3>
$aRegExp = StringRegExp("Die Abkürzung 'ISP' heißt 'Internet Service Provider'.",".*'(.*)'.*",3)
_ArrayDisplay($aRegExp)
Und was wurde in unserem Subpattern gespeichert?
'Internet Service Provider'. Dabei steht doch 'ISP' zuerst im Text. Das liegt daran, dass das * so gierig ist, dass es dem hinteren Teil alles wegfrisst. Es lässt nur so viel für die anderen Elemente des RegExp übrig, wie unbedingt nötig.
Hier ein anderes Beispiel:
[autoit]#include <Array.au3>
$aRegExp = StringRegExp("12-34.abc.def@mail.de","(.*)\.(.*)*@(.*)\.(.*)",3)
_ArrayDisplay($aRegExp)
Das erste Subpattern ist wieder sehr gierig, und nimmt sich 12-34.abc weg. Danach kommt der Punkt "\.".
Zuguterletzt folgt vor dem @ Zeichen noch ein SubPattern, welches das def aufnimmt.
Vorsicht: Da das 2te Subpattern noch einmal Quantifiziert wird, wird das "def" mit dem neuen Fund überschrieben. Da dieses mal aber Nichts "" übrig bleibt (Denn * ist auch mit Nichts zufrieden), wird das 2te Subpattern durch Nichts "" überschrieben.
Wir wollen also dem RegEx irgendwie klarmachen, dass das "*" nicht so gierig sein soll, sondern eher faul. Und das geht ganz leicht mit einem Fragezeichen "?" nach dem Quantifizer.
+? = Mindestens ein Treffer, ohne Grenze nach oben. Dieser Quantifizer ist nun faul, und wird versuchen so viel wie möglich für die anderen Elemente übrig zu lassen
*? = Mindestens null Treffer, ohne Grenze nach oben. Auch dieser Quantifizer ist nun faul.
?? = Ein Treffer oder überhaupt keiner. Wenn es möglich ist, findet dieser Quantifizer nichts. Wenn das nicht klappt "muss" er versuchen etwas zu finden. Ein ?? wird sehr selten bis nie benutzt. Ich wollte es der vollständigkeit halber aber mal auflisten.
Nachdem wir unsere faulen Quantifizer kennengelernt haben, nehmen wir uns das Beispiel von gerade nochmal zur Hand. Diesmal mit einem lazy "*" im ersten Subpattern.
[autoit]#include <Array.au3>
$aRegExp = StringRegExp("12-34.abc.def@mail.de","(.*?)\.(.*)*@(.*)\.(.*)",3)
_ArrayDisplay($aRegExp)
Das erste Subpattern frisst jetzt nur 12-34. Super oder?
5.1.3 Nicht-aufzeichnende Gruppierungen.
Eben haben wir ja schon Subpatterns kennengelernt. Manchmal möchte man allerdings RegEx-Elemente gruppieren, ohne dass sie in einem SubPattern gespeichert werden. Dazu verwendet man "?:" am Anfang einer Klammer. Ich nehme noch einmal das Beispiel zur Hand, welches wir bei dem OR-Operator hatten.
Wir haben unser Pattern, bei dem wir nur Sätze finden wollen, in an deren Ende Karl, Max oder Paul steht.
Testen wir dieses Pattern, wird uns immer nur der Name angezeigt, (Da er in ein SubPattern geschrieben wird)
$sString = "Mein Name ist Peter"& @CRLF
$sString &= "Mein Name ist Karl"& @CRLF
$sString &= "Mein Name ist Christian"& @CRLF
$sString &= "Mein Name ist Max"& @CRLF
$sString &= "Mein Name ist Paul"& @CRLF
$sString &= "Mein Name ist Manfred"& @CRLF
$aResult = StringRegExp($sString,"Mein Name ist (Karl|Max|Paul)",3)
_ArrayDisplay($aResult)
Fügen wir jedoch das "?:"-Flag am Anfang der Klammer ein,
so wird kein Subpattern mehr erstellt. Wir erhalten den vollen Satz als Ergebnis:
$sString = "Mein Name ist Peter"& @CRLF
$sString &= "Mein Name ist Karl"& @CRLF
$sString &= "Mein Name ist Christian"& @CRLF
$sString &= "Mein Name ist Max"& @CRLF
$sString &= "Mein Name ist Paul"& @CRLF
$sString &= "Mein Name ist Manfred"& @CRLF
$aResult = StringRegExp($sString,"Mein Name ist (?:Karl|Max|Paul)",3)
_ArrayDisplay($aResult)
5.2 Übersicht über Kapitel 5
Wir haben Quantifizer und Subpatterns kennengelernt.
5.3 Aufgaben
Schreibe ein Pattern, welches alle Funktionen einer .au3-Datei auflistet, und die Parameter für den Funktionsaufruf in ein Subpattern speichert.
Nutze dieses Script als vorlage:
#include <Array.au3>
$sRead = FileRead(StringTrimRight(@AutoItExe,11)&"Include\Array.au3")
;~ ClipPut($sRead)
$aRegExp = StringRegExp($sRead,"",3)
_ArrayDisplay($aRegExp)
[0] _ArrayAdd(ByRef $avArray, $vValue)
[1] ByRef $avArray, $vValue
[2] _ArrayBinarySearch(Const ByRef $avArray, $vValue, $iStart = 0, $iEnd = 0)
[3] Const ByRef $avArray, $vValue, $iStart = 0, $iEnd = 0
[4] _ArrayCombinations(ByRef $avArray, $iSet, $sDelim = "")
[5] ByRef $avArray, $iSet, $sDelim = ""
[6] _ArrayConcatenate(ByRef $avArrayTarget, Const ByRef $avArraySource, $iStart = 0)
[7] ByRef $avArrayTarget, Const ByRef $avArraySource, $iStart = 0
usw...
Filtere aus dem gegebenen Quelltext die Angaben über Rang, Geld und Einwohner und lege sie in SubPatterns ab.
Benutze den gegebenen RegExp-Tester. (Ich hatte mit Regexbuddy selbst Probleme, da die Regexbuddy eine mächtigere Regexp-Engine hat als AutoIt.)
Der wichtige Teil im Quelltext:
title='Medal Gold ' /> Rang: 250<br /><br /> <img src='http://stargods.de/images/icons/money.png' height='16' width='16' alt='Money' title='Money' /> <span class='bold' id='cash'>5.500.000</span> Gold<br /> <img src='http://stargods.de/images/icons/money_add.png' height='16' width='16' alt='Money Add' title='Money Add' /> 4.710.190 Gold / Std<br /><br /> <img src='http://stargods.de/images/icons/group.png' height='16' width='16' alt='Group' title='Group' /> <span class='bold' id='volk'>12.821.614</span> Volk<br />
#include <Array.au3>
#include <GuiRichEdit.au3>
#include <WindowsConstants.au3>
Global $bYellow ; If False, use Blue as next Color
Global $sIniPath = @AppDataDir & "\RegExpIt\Settings.ini"
$sString = "<?xml version='1.0' encoding='UTF-8'?> <!DOCTYPE html PUBLIC '-//W3C//DTD XHTML 1.1//EN' 'http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd'> <html xmlns='http://www.w3.org/1999/xhtml' xml:lang='en' > <head> <title>Kostenloses Browsergame | - </title> <meta name='keywords' content='browsergame, browsergames, stargods, online game, online games' /> <meta name='description' content='' /> <meta http-equiv='Content-Script-Type' content='text/javascript' /> <link rel='stylesheet' href='http://stargods.de/templates/style.css' type='text/css' /> <script type='text/javascript' src='http://stargods.de/templates/scripts/global.js'></script> <!--[if lt IE 7]><script defer='defer' type='text/javascript' src='http://stargods.de/templates/scripts/pngfix.js'></script><![endif]--> </head> <body onload='updateStats(4710190.12363,6650,5500000,12821613.8194)'> <script type='text/javascript' src='http://cf.xtremegn.de/scripts/wz_tooltip.js'></script> <div id='page'> <div id='top'> <div class='float' style='wid"
$sString &= "th:740px'> <iframe id='Footer728' name='Footer728' src='http://stargods.de/advertising/footer728.html' framespacing='0' frameborder='no' scrolling='no' width='728' height='90' allowtransparency='true' border='0' target='_blank' alt='' /></a></iframe> </div> <div class='float'> WEITERE BROWSERGAMES VON XGN <div id='gameselect'> <a href='http://kingofelements.de' target='_blank' title = 'King of Elements'><img src='http://stargods.de/images/spacer.gif' height='50%' width='33%' alt='King of Elements' title='King of Elements' /></a><a href='http://darkstory.de' target='_blank' title = 'Darkstory'><img src='http://stargods.de/images/spacer.gif' height='50%' width='33%' alt='Darkstory' title='Darkstory' /></a><a href='http://crazyfarm.de' target='_blank' title = 'Crazyfarm'><img src='http://stargods.de/images/spacer.gif' height='50%' width='33%' alt='Crazyfarm' title='Crazyfarm' /></a> <a href='http://inselcompany.de' target='_blank' title = 'Inselcompany'><img src='http://stargods.de/images"
$sString &= "/spacer.gif' height='50%' width='33%' alt='Inselcompany' title='Inselcompany' /></a><a href='http://oceansgarden.de' target='_blank' title = 'Oceansgarden'><img src='http://stargods.de/images/spacer.gif' height='50%' width='33%' alt='Oceansgarden' title='Oceansgarden' /></a><a href='http://dinoplanet.de' target='_blank' title = 'Dinoplanet'><img src='http://stargods.de/images/spacer.gif' height='50%' width='33%' alt='Dinoplanet' title='Dinoplanet' /></a> </div> </div><div class='clearer'></div> </div> <div style='position:absolute;width:1000px;background:#333;padding:0;filter:Alpha(opacity=50);opacity:0.75;moz-opacity:0.75'><marquee>+++ 18:11 Alfred_No_1 greift panther an +++ 18:10 Alfred_No_1 greift Wasabi an +++ 18:04 Heracles greift patrick228 an +++ 17:58 Heracles greift bartolomero an +++ 17:54 Jobi greift panther an +++ </marquee></div> <div id='left_city'> <a href='http://s1.stargods.de?nextCity=1' title = '?nextCity=1'><img src='http://stargods.de/images/spacer.gif' height='100"
$sString &= "' width='100%' alt='?nextCity=1' title='?nextCity=1' /></a> Grambranx </div> <div id='header'> <a href='http://s1.stargods.de/' title = 'Http://s1.stargods.de/'><img src='http://stargods.de/images/spacer.gif' height='226' width='100%' alt='Http://s1.stargods.de/' title='Http://s1.stargods.de/' /></a> <div style='height:15px;margin-left:82px;width:468px'> <iframe id='Linkblock' name='Linkblock' src='http://stargods.de/advertising/linkblock.html' framespacing='0' frameborder='no' scrolling='no' width='468' height='15' allowtransparency='true' border='0' target='_blank' alt='' /></a></iframe> </div> </div> <div id='left'> <div id='left_logo_4'> Daishi </div> <div id='left_ubersicht'> <img src='http://stargods.de/images/icons/star.png' height='16' width='16' alt='Star' title='Star' /> <b>548.168</b> Punkte<br /> <img src='http://stargods.de/images/icons/medal_gold_1.png' height='16' width='16' alt='Medal Gold ' title='Medal Gold ' /> Rang: 250<br /><br /> <img src='http://stargods.de/image"
$sString &= "s/icons/money.png' height='16' width='16' alt='Money' title='Money' /> <span class='bold' id='cash'>5.500.000</span> Gold<br /> <img src='http://stargods.de/images/icons/money_add.png' height='16' width='16' alt='Money Add' title='Money Add' /> 4.710.190 Gold / Std<br /><br /> <img src='http://stargods.de/images/icons/group.png' height='16' width='16' alt='Group' title='Group' /> <span class='bold' id='volk'>12.821.614</span> Volk<br /> <img src='http://stargods.de/images/icons/group_add.png' height='16' width='16' alt='Group Add' title='Group Add' /> 6.650 Zulauf / Std<br /><br /> Zufriedenheit:<br /> <div class='progressbar'><div style='width:100%'>100%</div></div><br /> Politische Zufriedenheit:<br /> <div class='progressbar'><div style='width:100%'>100%</div></div><br /> Militärische Zufriedenheit:<br /> <div class='progressbar'><div style='width:86%'>86%</div></div> </div> <div id='left_support'></div> <a href='http://board.xtremegn.de' title = 'Http://board.xtremegn.de'><img"
$sString &= " src='http://stargods.de/images/spacer.gif' id='left_forum' alt='Http://board.xtremegn.de' title='Http://board.xtremegn.de' /></a> <a href='http://s1.stargods.de/contact' title = 'Kontakt'><img src='http://stargods.de/images/spacer.gif' id='left_kontakt' alt='Kontakt' title='Kontakt' /></a> </div> <div id='content'> <ul id='topmenu'> <li><a href='http://s1.stargods.de/einheiten'>Einheiten</a></li><li><a href='http://s1.stargods.de/gebaude'>Gebäude</a></li><li><a href='http://s1.stargods.de/forschung'>Forschung</a></li><li><a href='http://s1.stargods.de/status'>Status </a></li><li><a href='http://s1.stargods.de/staat'>Staat</a></li><li><a href='http://s1.stargods.de/krieg'>Krieg</a></li><li><a href='http://s1.stargods.de/groups'>Allianzen</a></li><li><a href='http://s1.stargods.de/rangliste'>Rangliste</a></li><li><a href='http://s1.stargods.de/welt'>Welt</a></li> </ul> <div style='padding:16px 10px 10px'> <!-- <div class='title'><h2>Vorsicht!</h2></div><div class='box'><div cl"
$sString &= "ass='float center' style='width:100px'><img src='http://stargods.de/images/symbols/error64.png' height='64' width='64' alt='Vorsicht!' title='Vorsicht!' /></div><div class='float75'><div style='margin:15px 10px 5px;font-size:105%'>Wir haben in dieser Version viele Änderungen am Grundsystem, sowie 'spontane' Erweiterungen vorgenommen. Auf Grund des kurzen Zeitrahmens können wir eine Fehlerfreiheit leider nicht garantieren! Spielt deshalb die ersten Tage bitte besonders aufmerksam und teilt uns Fehler über den Kontakt mit!<br /><br />Danke, das Stargods Team</div></div><div class='clearer'></div></div><div class='box_bottom'></div> --> <div class='title'><h2> </h2></div><div class='box'><div class='float' style='width:52.99%;padding-top:5px'> <iframe id='Footer300links' name='Footer300links' src='http://stargods.de/advertising/footer300.html' framespacing='0' frameborder='no' scrolling='no' width='300' height='250' allowtransparency='true' border='0' target='_blank' a"
$sString &= "lt='' /></a></iframe> </div><div class='float justify' style='width:46.99%'> <h1>Willkommen zurück!</h1><br /> Hier hast du eine kleine Übersicht über den aktuellen Status deiner Stadt und deines Volkes. Um nähere Informationen zu den jeweiligen Punkten zu erlangen, benutze bitte die Hauptnavigation.<br /><br /> <div id='belohnungen'></div> </div><div class='clearer'></div></div><div class='box_bottom'></div><br /> <div class='title'><h2>Unterstützt Stargods</h2></div><div class='box bold center'>Helft mit einfachen Mitteln!<br /><br /> <b><font color='#ffff00' face='Arial' size='2'>Zähle zu unserem stargods-Team.</font></b><br /> <a href='http://www.kostenlose-browsergames.de' target='_blank'><img src='http://stargods.de/images/kostenlosebrowsergames.gif' alt='Kostenlose Browsergames' style='border: 1px solid #212121;margin-top:5px;' width='88' height='31' /></a> <br /><font face='Arial' size='1' color='#FFFF00'>Vote <b>1x am Tag</b> für uns.</font><"
$sString &= "br /><br /> Und nun wünsche ich euch eine erfolgreiche Zeit.</div><div class='box_bottom'></div><br /> <div class='title'><h2>Neuigkeiten</h2></div><div class='box'>Es sind noch keine Neuigkeiten vorhanden</div><div class='box_bottom'></div> <script type='text/javascript' src='http://stargods.de/layer.js'></script> </div></div> <div id='right'> <p style='margin-bottom:7px'><img src='http://stargods.de/images/icons/layout_delete.png' height='16' width='16' alt='Layout Delete' title='Layout Delete' /> Werbefrei: <a href='http://s1.stargods.de/ucp/adfree'>Aktivieren</a></p> <p style='margin-bottom:8px'><img src='http://stargods.de/images/icons/user_add.png' height='16' width='16' alt='Freundesliste (0)' /> <a href='http://s1.stargods.de/messages/contacts'>Freundesliste (0)</a><br /> <img src='http://stargods.de/images/icons/user_delete.png' height='16' width='16' alt='Blockierliste' /> <a href='http://s1.stargods.de/messages/blocked'>Blockierliste</a><br /> <img src='http://stargods."
$sString &= "de/images/icons/group.png' height='16' width='16' alt='Allianz: IT-World' /> <a href='http://s1.stargods.de/groups/389'>Allianz: <b>IT-World</b></a> </p> <p><img src='http://stargods.de/images/icons/user.png' height='16' width='16' alt='Profil betrachten' /> <a href='http://s1.stargods.de/profil'>Profil betrachten</a><br /> <img src='http://stargods.de/images/icons/user_edit.png' height='16' width='16' alt='Profil bearbeiten' /> <a href='http://s1.stargods.de/ucp'>Profil bearbeiten</a><br /> <img src='http://stargods.de/images/icons/email.png' height='16' width='16' alt='Nachrichten (2)' /> <a href='http://s1.stargods.de/messages'>Nachrichten (2)</a><br /> <img src='http://stargods.de/images/icons/delete.png' height='16' width='16' alt='Ausloggen' /> <a href='http://s1.stargods.de/ucp/logout'>Ausloggen</a></p> <div style='margin-top:55px'> <iframe id='Sidebar' name='Sidebar' src='http://stargods.de/advertising/sidebar.html' framespacing='0' frameborder='no' scrolling='no' width='160' h"
$sString &= "eight='600' allowtransparency='true' border='0' target='_blank' alt='' /></a></iframe> </div> </div><div class='clearer'></div> <div id='footer'> <p class='bold'><a href='http://s1.stargods.de/contact'>Kontakt</a> · <a href='http://s1.stargods.de/'>Neuigkeiten</a> · <a href='http://s1.stargods.de/agb'>AGB</a> · <a href='http://s1.stargods.de/datenschutz'>Datenschutz</a> · <a href='http://s1.stargods.de/impressum'>Impressum</a></p> Copyright © 2008-10 XtremeGN.de - Alle Rechte vorbehalten. Webdesign von <a href='http://gnomdesign.de' target='_blank'>Gnomdesign.de</a> </div> </div> </body> </html>"
$aGUIRes = StringSplit(IniRead($sIniPath, "General Settings", "Resolution", "800x600"), "x", 2)
$hGUI = GUICreate("RegExpIt", $aGUIRes[0], $aGUIRes[1], -1, -1, $WS_OVERLAPPEDWINDOW)
GUISetFont(12)
$hRE_RegExp = _GUICtrlRichEdit_Create($hGUI, "", 10, 10, 445, 120, BitOR($ES_MULTILINE, $WS_VSCROLL, $ES_AUTOVSCROLL))
_GUICtrlRichEdit_SetFont($hRE_RegExp, 12)
$hRE_TestString = _GUICtrlRichEdit_Create($hGUI, $sString, 10, 170, 780, 200)
_GUICtrlRichEdit_SetFont($hRE_TestString, 12)
$hRE_Matches = _GUICtrlRichEdit_Create($hGUI, "", 10, 390, 780, 200)
_GUICtrlRichEdit_SetFont($hRE_Matches, 15)
GUISetState()
[/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]While 1
$nMsg = GUIGetMsg()
Switch $nMsg
Case -3
GUIDelete($hGUI) ;GUI löschen, wegen RichEdit.
Exit
EndSwitch
_RichEdit_ApplyRegExp($hRE_RegExp)
WEnd
Func _RichEdit_ApplyRegExp(ByRef $hRichEdit)
If _GUICtrlRichEdit_IsModified($hRichEdit) Then
_GUICtrlRichEdit_SetModified($hRichEdit, False)
$aTmp = StringRegExp(_RichEdit_GetText($hRE_TestString), _RichEdit_GetText($hRE_RegExp), 3)
If Not @error Then
_GUICtrlRichEdit_SetText($hRE_Matches, _ArrayToString($aTmp, @CRLF))
Global $bYellow = True
$aSel = _GUICtrlRichEdit_GetSel($hRichEdit) ; Get curren Cursor Pos.
__RichEdit_ColorViaRegExp($hRE_Matches)
;~ __RichEdit_ColorViaRegExp($hRE_TestString)
_GUICtrlRichEdit_SetSel($hRichEdit, $aSel[0], $aSel[1]) ;restore Cursor Pos
Else
_GUICtrlRichEdit_SetText($hRE_Matches, "")
EndIf
EndIf
EndFunc ;==>_RichEdit_ApplyRegExp
Func _RichEdit_GetText($hRichEdit)
;SEuBo
$aPos = _GUICtrlRichEdit_GetSel($hRichEdit)
_GUICtrlRichEdit_AppendText($hRichEdit, " ")
$sRet = StringReplace(_GUICtrlRichEdit_GetText($hRichEdit, True), @CR & " ", @CR)
_GUICtrlRichEdit_SetText($hRichEdit, $sRet)
_GUICtrlRichEdit_SetSel($hRichEdit, $aPos[0], $aPos[1])
_GUICtrlRichEdit_SetModified($hRichEdit, False)
Return $sRet
EndFunc ;==>_RichEdit_GetText
Func __RichEdit_ColorViaRegExp($hRichEdit)
$aTmp = StringRegExp(_RichEdit_GetText($hRE_TestString), _RichEdit_GetText($hRE_RegExp), 3)
_GUICtrlRichEdit_SetSel($hRichEdit, 0, -1, True)
_GUICtrlRichEdit_SetCharBkColor($hRichEdit, 0xFFFFFF)
If _RichEdit_GetText($hRE_RegExp) <> "" Then
Local $sText = _RichEdit_GetText($hRichEdit), $iCounter = 0
Global $bYellow = True
If $aTmp[0] = "" Then Return SetError(@error,@extended,"")
For $i = 0 To UBound($aTmp) - 1
$bYellow = Not $bYellow
Local $iPos = StringInStr($sText, $aTmp[$i], 1) - 1
_GUICtrlRichEdit_SetSel($hRichEdit, $iPos + $iCounter, $iPos + $iCounter + StringLen($aTmp[$i]), True)
If $bYellow Then _GUICtrlRichEdit_SetCharBkColor($hRichEdit, 0xFFF000)
If Not $bYellow Then _GUICtrlRichEdit_SetCharBkColor($hRichEdit, 0x80C0FF)
$sText = StringTrimLeft($sText, $iPos + 1)
$iCounter += $iPos + ($hRichEdit <> $hRE_Matches)
Next
EndIf
_GUICtrlRichEdit_SetModified($hRichEdit, False)
EndFunc ;==>__RichEdit_ColorViaRegExp
Schreibe ein Pattern, dass alle Daten in der Liste findet. Falsche Daten wie 31.02.2008 können vorerst ignoriert werden. Dazu kommen wir dann beim konditionalen RegExp.
22.12.2004
01.05.10
6.11.2003
28.2.07
16.06.06
11.11.11
20.02.2002
#include <Array.au3>
$sString = _
"22.12.2004" & @CRLF & _
"01.05.10" & @CRLF & _
"6.11.2003" & @CRLF & _
"28.2.07" & @CRLF & _
"16.06.06" & @CRLF & _
"11.11.11" & @CRLF & _
"20.02.2002" & @CRLF
$aArray = StringRegExp($sString,"",3)
_ArrayDisplay($aArray)
6. Konditionales RegExp
Zuerst einmal: Wir sind über den Berg! Den schwersten Teil haben wir jetzt hinter uns.
Das soll aber nicht heißen, dass das kommende Kapitel es nicht in sich hat
Vorbereitung: Stell die RegEx Engine in RegExBuddy (Combobox oben links) auf "PCRE" !
Konditionales RegExp arbeitet nach einem If-Then-Else Prinzip. Der Syntaxaufruf lautet
Jetzt kommt erstmal ein ausführliches Beispiel. Ich werde den kompletten "Zusammenbau" des Patterns erklären.
So haben wir auch noch etwas Wiederholungsstoff
Wir haben folgenden String:
DE: 02.01.2009
US: 11-19-2008
UK: 5-10-2004
DE: 27.3.99
DE: 04.12.2002
US: 9-8-98
UK: 08-12-08
Wie ihr seht, sind das Daten. Einmal in US/UK-Schreibweise, und einmal in der deutschen Schreibweise.
Wir möchten diese Daten finden. Wir möchten aber nur ein Arrayelement pro gefundenem Datum.
Jedes Arrayelement soll nur das Datum, nicht aber "DE,US oder UK" enthalten.
Was wir machen müssen ist also folgendes:
Falls die Zeile mit "DE:" beginnt, suchen wir nach deutschem Datumsformat,
Falls nicht nach dem Englischen.
Dann schreiben wir zuerst einen RegExp für das deutsche Format.
Natürlich erstellen wir kein Subpattern dafür.
Beginnend mit "DE: " sollen Zahlen von 0-31 gefunden werden. Egal ob 1 oder 2-stellig.
Danach folgt ein literaler Punkt
Nun Zahlen von 0-12 gefolgt von einem Punkt.
Nun nur noch die Jahreszahl.
Dieses Pattern soll gefunden werden, wenn der String mit "DE: " anfängt.
Das DE soll aber nicht gefunden werden. Deswegen kommt es in ein nicht-fangendes klammerpaar (im Then-Part)
Ist euch auf aufgefallen, dass wir "^DE\: " 2 mal schreiben mussten? Das könnte man zwar durch ein Subpattern lösen, welches man per \1 ansteuert (Backtracking - dazu komme ich später nochmal näher), aber wir wollten ja explizit nur ein Array Element. Im nächtsen Teil bei den Assertionen sehen wir, dass es auch einfach geht, denn Assertionen sind mit Konditionen verknüpfbar.
Jetzt also das englische Datum:
Am Zeilenanfang sollte "UK: " oder "US: " zu finden sein.
gefolgt von Monat, einem Bindestrich dem Tag, Bindestrich und jahreszahl.
Das ganze soll in ein Subpattern (damit wir UK oder US nicht im Ergebnis haben)
Das ganze sieht jetzt so aus:
(?(?=^DE\: )[^ ]+ ((?:3[0-1]|[0-2]?\d)\.(?:1[0-2]|0?\d)\.(?:19|20)?\d\d)|(?(?=^(?:UK|US))[^ ]+ ((?:1[0-2]|0?\d)\-(?:3[0-1]|[0-2]?\d)\-(?:19|20)?\d\d)))
Aber es werden ja jetzt immer noch der 30.02 und 31.02 gefunden?!
Tja selbst schuld! Dann halt auf die harte Tour
(?(?=^DE: )[^ ]+ ((?(?=\d{2}\.0?2)[0-2]?\d\.0?2\.(?:19|20)?\d\d|(?:3[01]|[0-2]?\d)\.(?:1[0-2]|0?\d)\.(?:19|20)?\d\d))|(?(?=^U[SK])[^ ]+ ((?(?=0?2\-)0?2\-[0-2]?\d\-(?:19|20)?\d\d|(?:0?\d|1[0-2])\-(?:3[01]|[0-2]?\d)\-(?:19|20)?\d\d))))
Dieses Pattern hat mich übrigens ca 35 mins gekostet - also selbst für mich geht sowas nicht mal "eben so von der Hand".
Dieses Pattern überprüft nun, ob der Monat ein Februar ist. Wenn ja, werden Tage von 0-29 gesucht. Wenn nicht, Tage von 0-31.
Und jetzt baut ihr das Ding mal ohne RegExbuddy zusammen
(?(?=^DE: )[^ ]+ ((?(?=\d{2}\.0?2)[0-2]?\d\.0?2\.(?:19|20)?\d\d|(?:3[01]|[0-2]?\d)\.(?:1[0-2]|0?\d)\.(?:19|20)?\d\d))|(?(?=^U[SK])[^ ]+ ((?(?=0?2\-)0?2\-[0-2]?\d\-(?:19|20)?\d\d|(?:0?\d|1[0-2])\-(?:3[01]|[0-2]?\d)\-(?:19|20)?\d\d))))
Wenn "DE:" gefunden wurde, dann
Finde mindestens ein aber unendlich viele Zeichen, die keine Leerzeichen sind.
Finde ein literales Leerzeichen
Öffne ein Subpattern
Wenn "\d{2}\.0?2\." zutrifft, dann ; Wenn Monat Februar ist,
Finde alle Zahlen von 0-29. ; Tag
Finde einen literalen Punkt.
Finde "02" oder "2". ; Monat
Finde einen literalen Punkt.
Öffne eine nicht-fangende Klammer. ; Jahr
Finde 19 oder 20.
Schließe die nicht-fangende Klammer.
Der Inhalt des klammerpaares darf 0-1 mal gefunden werden.
Finde 2 aufeinanderfolgende Zahlen von 0-9.
Andernfalls
Öffne eine nicht-fangende Klammer. ; Tag
Finde alle Zahlen von 30-31 oder 0-29
Schließe die nicht-fangende Klammer.
Finde einen literalen Punkt.
Öffne eine nicht-fangende Klammer. ; Monat
Finde eine Zahl von 10-12 oder 0-9.
Schließe die nicht-fangende Klammer.
Finde einen literalen Punkt.
Öffne eine nicht-fangende Klammer. ; Jahr
Finde 19 oder 20.
Schließe die nicht-fangende Klammer.
Der Inhalt des klammerpaares darf 0-1 mal gefunden werden.
Finde 2 aufeinanderfolgende Zahlen von 0-9.
Danach
Schließe ein Subpattern.
Andernfalls
Wenn "UK: " oder "US: " gefunden wurde, dann
Finde mindestens ein aber unendlich viele Zeichen, die keine Leerzeichen sind.
Finde ein literales Leerzeichen
Öffne ein Subpattern
Wenn "0?2\-" zutrifft, dann ; Wenn Monat Februar ist,
Finde "02" oder "2". ; Monat
Finde einen literalen Bindestrich
Finde alle Zahlen von 0-29. ; Tag
Finde einen literalen Bindestrich
Öffne eine nicht-fangende Klammer. ; Jahr
Finde 19 oder 20.
Schließe die nicht-fangende Klammer.
Der Inhalt des klammerpaares darf 0-1 mal gefunden werden.
Finde 2 aufeinanderfolgende Zahlen von 0-9.
Andernfalls
Öffne eine nicht-fangende Klammer. ; Monat
Finde eine Zahl von 10-12 oder 0-9.
Schließe die nicht-fangende Klammer.
Finde einen literalen Bindestrich
Öffne eine nicht-fangende Klammer. ; Tag
Finde alle Zahlen von 30-31 oder 0-29
Schließe die nicht-fangende Klammer.
Finde einen literalen Bindestrich
Öffne eine nicht-fangende Klammer. ; Jahr
Finde 19 oder 20.
Schließe die nicht-fangende Klammer.
Der Inhalt des klammerpaares darf 0-1 mal gefunden werden.
Finde 2 aufeinanderfolgende Zahlen von 0-9.
Danach
Schließe ein Subpattern.
Danach
Alles anzeigen
6.1 Übersicht über Kapitel 6
Wir haben konditionales RegExp kennengelernt.
aufgerufen.
6.2 Aufgaben
Baue das Pattern aus Aufgabe 5.3.3 (Datums-Checker) so um, dass es den 30 & 31 Februar ausschließt!
Aufgabe 2:
Baue ein Pattern, das korrekte IPv4-Adressen findet. Von 0.0.0.0 bis 255.255.255.255
7. Assertionen und Backreference
7.1 Assertionen
Mit einer Assertion kann man angeben, dass etwas vor (Lookahead) oder hinter (Lookbehind) einem anderen RegExp-Abschnitt stehen soll.
Eine Assertion hat den Vorteil, dass der Fund nicht mit ins Ergebnis übernommen wird. Schaut euch am besten mal das Beispiel an.
Wir schauen uns mal einen positiven Lookahead an:
foobar
findet "bar", weil "foo" davor gefunden wurde. Würde der RegEx allerdings
heißen, würde die RegExp Maschine nichts finden. Weil dem "bar" kein "zoo" sondern ein "foo" vorangeht.
Das ganze kann man auch verneinen, und zu einem Negativen Lookahead umwanden. Aus
wird dann
Mit diesem Pattern finden wir im String "foobar" auch wieder bar, weil dem "bar" kein "zoo" vorangeht.
Das gleiche gibts natürlich auch als sog. Lookbehind.
Diesmal suchen wir "foo", wenn "bar" folgt
oder auch "foo", wenn kein "boo" folgt:
#include <Array.au3>
[/autoit] [autoit][/autoit] [autoit]; Positiver Lookahead (?<=)
$aResult = StringRegExp("foobar","(?<=foo)bar", 3)
_ArrayDisplay($aResult,"(?<=foo)bar")
; Negativer Lookahead (?<!)
$aResult = StringRegExp("foobar","(?<!zoo)bar", 3)
_ArrayDisplay($aResult,"(?<!zoo)bar")
; Positiver Lookbehind (?=)
$aResult = StringRegExp("foobar","foo(?=bar)", 3)
_ArrayDisplay($aResult,"foo(?=bar)")
; Negativer Lookbehind (?!)
$aResult = StringRegExp("foobar","foo(?!boo)", 3)
_ArrayDisplay($aResult,"foo(?!bar)")
Achtung: Eine Bedingung ist an den Suchbegriffen im Assertion allerdings zu stellen: ihre Länge muss definiert sein, das heißt, es können keine Quantifizierer verwendet werden! Die Assertion "(?<=\d+,)\d\d" führt zu einem Laufzeitfehler.
Assertionen understützen den OR-Operator (allerdings nicht in tiefere Klammerebenen).
Ist erlaubt. Das hier hingegen nicht:
Assertionen können mit konditionalem RegExp verknüpft werden. Schaut euch das Kapitel noch mal an und ihr werdet sehen, dass wir immer einen positiven Lookbehind (?=) benutzt haben. Statt
geht also auch
Je nachdem was man gerade braucht.
Assertionen sind verschachtelbar und auch hintereinander verwendbar.
7.2 Backreference
Ich habe es ja schon im Teil über Subpatterns erwähnt. Man kann sich auf das Ergebnis eines Subpatterns, oder besser gesagt auf dessen Inhalt zurückbeziehen.
Lange Rede Kurzer Sinn:
Rad und Handschlag
Rad und Radschlag_
Hand und Handschlag
Hand und Anschlag
Es wird also immer mittels \1 das Ergebnis des ersten Subpattern geprüft und später im RegExp verwendet. Deswegen findet dieses Pattern auch nur "Hand und Handschlag " und "Rad und Radschlag"
Möchte man die Subpattern-nummer von einer "richtigen" zahl trennen, so benutzt man geschweifte klammern.
Bsp: Wir wollen uns per Backreference auf das 4te Subpattern beziehen. Danach soll eine 9 stehen.
\49 findet allerdings das 49te Subpattern. Deswegen machen wir folgendes:
\{4}9
Backreference kann aber auch mit konditionalem RegExp verwendet werden. Der Syntaxaufruf ist dann
Beispiel:
[autoit]#include <Array.au3>
$sString = "Test dieser Satz ist ein Test"
$aTmp = StringRegExp($sString,"(e)?(?(1)(r)|in)",3)
_ArrayDisplay($aTmp)
Wir suchen also erst nach "e" und schreiben es in ein Subpattern.
Nun kommt die Kondition (?(1)...|...). Wenn Subpattern 1 am Match teilgenommen hat, dann soll nach "r" gesucht werden. (Damit wir es in den Ergebnissen angezeigt bekommen, müssen wir das natürlich auch in einem Subpattern speichern. Sollte das 1. Subpattern nciht am Match teilgenommen haben, so wird der Else-Teil der Kondition aktiv, und es wird nach "in" gesucht.
Wer's braucht
7.3 Übersicht über Kapitel 7
In diesem Teil lernten wir etwas über Assertionen. Desweiteren haben wir unser Wissen zu Backreferencen aufgefrischt, und das über konditionalen RegExp erweitert.
7.4 Kapitel 7 - Aufgaben
1. Wir haben ein einfaches Verschlüsselungsprogramm geschrieben, in dem ein Buchstabe in einem Text durch einen anderen ersetzt wird.
$hGUI = GUICreate("",120,60)
$hInput = GUICtrlCreateInput("",10,10,100,20)
$hButton = GUICtrlCreateButton("OK",10,35,100,20)
GUISetState()
While 1
$nMsg = GUIGetMsg()
Switch $nMsg
Case -3
Exit
Case $hButton
GUICtrlSetData($hInput, _Crypt(GUICtrlRead($hInput)))
EndSwitch
WEnd
Func _Crypt($sString)
$sString = StringReplace($sString,"a","z")
$sString = StringReplace($sString,"b","y")
$sString = StringReplace($sString,"c","x")
$sString = StringReplace($sString,"d","w")
$sString = StringReplace($sString,"e","v")
$sString = StringReplace($sString,"f","u")
$sString = StringReplace($sString,"g","t")
$sString = StringReplace($sString,"h","s")
$sString = StringReplace($sString,"i","r")
$sString = StringReplace($sString,"j","q")
$sString = StringReplace($sString,"k","p")
$sString = StringReplace($sString,"l","o")
$sString = StringReplace($sString,"m","n")
$sString = StringReplace($sString,"n","m")
$sString = StringReplace($sString,"o","l")
$sString = StringReplace($sString,"p","k")
$sString = StringReplace($sString,"q","j")
$sString = StringReplace($sString,"r","i")
$sString = StringReplace($sString,"s","h")
$sString = StringReplace($sString,"t","g")
$sString = StringReplace($sString,"u","f")
$sString = StringReplace($sString,"v","e")
$sString = StringReplace($sString,"w","d")
$sString = StringReplace($sString,"x","c")
$sString = StringReplace($sString,"y","b")
$sString = StringReplace($sString,"z","a")
Return $sString
EndFunc
Nun haben wir allerdings ein Problem: Die Buchstaben, die ersetzt werden, werden sofort wieder zurück übersetzt. (logisch!). Finde eine Lösung für dieses Problem. (Da es ein RegExp Tutorial ist, sollte die Lösung mit StringRegExp/StringRegExpReplace arbeiten.)
Wir schreiben die Buchstaben, die ersetzt wurden, in eckige Klammern. Ersetzt werden sollen dann natürlich auch nur die Buchstaben, die NICHT in eckigen Klammern stehen. (Eine Assertion ist hier von Vorteil!)
Danach werden alle eckigen Klammern entfernt.
$hGUI = GUICreate("", 120, 60)
$hInput = GUICtrlCreateInput("", 10, 10, 100, 20)
$hButton = GUICtrlCreateButton("OK", 10, 35, 100, 20)
GUISetState()
While 1
$nMsg = GUIGetMsg()
Switch $nMsg
Case -3
Exit
Case $hButton
GUICtrlSetData($hInput, _Crypt(GUICtrlRead($hInput)))
EndSwitch
WEnd
Func _Crypt($sString)
; Ja ich weiß, mit einem 2D-Array und einer For-Next Schleife wäre es 200 mal kürzer. Aber ich wollte es nicht unnötig kompliziert machen.
$sString = _StringReplace($sString, "a", "z")
$sString = _StringReplace($sString, "b", "y")
$sString = _StringReplace($sString, "c", "x")
$sString = _StringReplace($sString, "d", "w")
$sString = _StringReplace($sString, "e", "v")
$sString = _StringReplace($sString, "f", "u")
$sString = _StringReplace($sString, "g", "t")
$sString = _StringReplace($sString, "h", "s")
$sString = _StringReplace($sString, "i", "r")
$sString = _StringReplace($sString, "j", "q")
$sString = _StringReplace($sString, "k", "p")
$sString = _StringReplace($sString, "l", "o")
$sString = _StringReplace($sString, "m", "n")
$sString = _StringReplace($sString, "n", "m")
$sString = _StringReplace($sString, "o", "l")
$sString = _StringReplace($sString, "p", "k")
$sString = _StringReplace($sString, "q", "j")
$sString = _StringReplace($sString, "r", "i")
$sString = _StringReplace($sString, "s", "h")
$sString = _StringReplace($sString, "t", "g")
$sString = _StringReplace($sString, "u", "f")
$sString = _StringReplace($sString, "v", "e")
$sString = _StringReplace($sString, "w", "d")
$sString = _StringReplace($sString, "x", "c")
$sString = _StringReplace($sString, "y", "b")
$sString = _StringReplace($sString, "z", "a")
Return _CleanUp($sString)
EndFunc ;==>_Crypt
Func _StringReplace($sString, $sSearch, $sReplace)
Return StringRegExpReplace($sString, "(?<!\[)" & $sSearch & "(?!\])", "[" & $sReplace & "]")
EndFunc ;==>_StringReplace
Func _CleanUp($sString)
Return StringRegExpReplace($sString, "\[(\w+?)\]", "\1")
EndFunc ;==>_CleanUp
Aufgabe 2:
Wir haben eine Liste mit eMail-Adressen. Schreibe einen RegExp, dass mithilfe von Backreference doppelte Namen findet. (Der Hostname wie zB. gmx.de kann außer Acht gelassen werden.)
=======================================
LG SEuBo
Da steht auch "If WinActivate" und nicht "WinActive"
Eher so?
While 1 * sleep(10)
If WinActive("Info über AutoCAD® Mechanical 2009", "") Then
MsgBox(0, "", "Fall 1")
ElseIf WinActive("AutoCAD", "Änderungen in") Then
MsgBox(0, "", "Fall 2")
ElseIf WinActive("Optionen", "") Then
MsgBox(0, "", "Fall 3")
EndIf
WEnd
//EDIT Jetzt aber xD
Soo jetzt aber:
$hGUI = GUICreate("", 120, 60)
$hInput = GUICtrlCreateInput("", 10, 10, 100, 20)
$hButton = GUICtrlCreateButton("OK", 10, 35, 100, 20)
GUISetState()
$aSnR = IniReadSection(@ScriptDir & "\config.ini", "words")
If @error Then Exit MsgBox(0,"","Fehler beim lesen der ini")
While 1
$nMsg = GUIGetMsg()
Switch $nMsg
Case -3
Exit
Case $hButton
GUICtrlSetData($hInput, _Crypt(GUICtrlRead($hInput)))
EndSwitch
WEnd
Func _Crypt($sString)
For $i = 1 To $aSnR[0][0]
$sString = _StringReplace($sString, $aSnR[$i][0], $aSnR[$i][1])
Next
Return StringRegExpReplace($sString, "\[([^\]]+)\]", "\1")
EndFunc ;==>_Crypt
Func _StringReplace($sString, $sSearch, $sReplace)
Return StringRegExpReplace($sString, "(?<!\[)" & $sSearch & "(?!\])", "[" & $sReplace & "]")
EndFunc ;==>_StringReplace
IniRead("asdasa.2910351061","Sektion","Key","Default")
[/autoit]Ist doch wurst, wie die ini heißt.
Wie wird der Text denn überhaupt ausm Inet eingelesen?
InetRead? InetGet?!
Wenn dich StringRegExp interessiert:
Mein Tutorial: http://tinyurl.com/yglf972
BugFix Tutorial (Sry BugFix, aber das hab ich selbst nie verstanden): http://www.bug-fix.info/PathCheck.htm
Schonmal
[autoit]_GUICtrlListView_SetUnicodeFormat()
[/autoit]
probiert?
Nur "Zitat"
"Zitat von WORLD_KILLER"
"Zitat von WORLD_KILLER" (mit Link)
Oder:
Einfach Text markieren -> Zitieren Button -> Textstelle zum Zitieren auswählen (oder Direkt Zitieren)