tcl
Reguläre Ausdrücke
Suche…
Syntax
- Regexx wechselt? exp string? matchVar? subMatchVar subMatchVar ...?
- RegSchalter? exp string subSpec? varName?
Bemerkungen
Dieses Thema ist nicht dazu gedacht, reguläre Ausdrücke selbst zu diskutieren. Es gibt viele Ressourcen im Internet, die reguläre Ausdrücke und Werkzeuge zum Erstellen regulärer Ausdrücke erklären.
In diesem Thema werden die gängigen Optionen und Methoden für die Verwendung regulärer Ausdrücke in Tcl sowie einige Unterschiede zwischen Tcl und anderen regulären Ausdrücken erläutert.
Reguläre Ausdrücke sind im Allgemeinen langsam. Die erste Frage, die Sie stellen sollten, lautet: "Benötige ich wirklich einen regulären Ausdruck?". Nur das, was Sie wollen. Wenn Sie die anderen Daten nicht benötigen, stimmen Sie nicht überein.
Für die Zwecke dieser Beispiele für reguläre Ausdrücke wird der Schalter -expanded verwendet, um den regulären Ausdruck kommentieren und erklären zu können.
Matching
Mit regexp Befehl " regexp wird ein regulärer Ausdruck mit einer Zeichenfolge regexp .
# This is a very simplistic e-mail matcher.
# e-mail addresses are extremely complicated to match properly.
# there is no guarantee that this regex will properly match e-mail addresses.
set mydata "send mail to [email protected] please"
regexp -expanded {
\y # word boundary
[^@\s]+ # characters that are not an @ or a space character
@ # a single @ sign
[\w.-]+ # normal characters and dots and dash
\. # a dot character
\w+ # normal characters.
\y # word boundary
} $mydata emailaddr
puts $emailaddr
[email protected]
Der regexp Befehl gibt den Wert 1 (wahr) zurück, wenn eine Übereinstimmung gefunden wurde, oder 0 (falsch), wenn dies nicht der Fall ist.
set mydata "hello wrld, this is Tcl"
# faster would be to use: [string match *world* $mydata]
if { [regexp {world} $mydata] } {
puts "spelling correct"
} else {
puts "typographical error"
}
Um alle Ausdrücke in einigen Daten abzugleichen, verwenden Sie die Option -all und die Option -inline, um die Daten zurückzugeben. Beachten Sie, dass die Standardeinstellung ist, Zeilenumbrüche wie andere Daten zu behandeln.
# simplistic english ordinal word matcher.
set mydata {
This is the first line.
This is the second line.
This is the third line.
This is the fourth line.
}
set mymatches [regexp -all -inline -expanded {
\y # word boundary
\w+ # standard characters
(?:st|nd|rd|th) # ending in st, nd, rd or th
# The ?: operator is used here as we don't
# want to return the match specified inside
# the grouping () operator.
\y # word boundary
} $mydata]
puts $mymatches
first second third fourth
# if the ?: operator was not used, the data returned would be:
first st second nd third rd fourth th
Newline-Handling
# find real numbers at the end of a line (fake data).
set mydata {
White 0.87 percent saturation.
Specular reflection: 0.995
Blue 0.56 percent saturation.
Specular reflection: 0.421
}
# the -line switch will enable newline matching.
# without -line, the $ would match the end of the data.
set mymatches [regexp -line -all -inline -expanded {
\y # word boundary
\d\.\d+ # a real number
$ # at the end of a line.
} $mydata]
puts $mymatches
0.995 0.421
Unicode erfordert keine besondere Behandlung.
% set mydata {123ÂÃÄÈ456}
123ÂÃÄÈ456
% regexp {[[:alpha:]]+} $mydata match
1
% puts $match
ÂÃÄÈ
% regexp {\w+} $mydata match
1
% puts $match
123ÂÃÄÈ456
Dokumentation: regexp re_syntax
Gierige und nicht gierige Quantifizierer mischen
Wenn Sie als ersten Quantifizierer ein gieriges Spiel haben, wird das gesamte RE gierig sein,
Wenn Sie als ersten Quantifizierer eine nicht gierige Übereinstimmung haben, wird die gesamte RE nicht gierig sein.
set mydata {
Device widget1: port: 156 alias: input2
Device widget2: alias: input1
Device widget3: port: 238 alias: processor2
Device widget4: alias: output2
}
regexp {Device\s(\w+):\s(.*?)alias} $mydata alldata devname devdata
puts "$devname $devdata"
widget1 port: 156 alias: input2
regexp {Device\s(.*?):\s(.*?)alias} $mydata alldata devname devdata
puts "$devname $devdata"
widget1 port: 156
Im ersten Fall ist das erste \ w + gierig, also werden alle Quantifizierer als gierig markiert und das. *? entspricht mehr als erwartet.
Im zweiten Fall der erste. *? ist nicht gierig und alle Quantifizierer werden als nicht gierig markiert.
Andere reguläre Ausdrücke haben möglicherweise kein Problem mit gierigen / nicht-gierigen Quantifizierern, aber sie sind viel langsamer.
Henry Spencer schrieb : ... Das Problem ist , dass es sehr, sehr schwer , eine Verallgemeinerung dieser Erklärungen zu schreiben , die bedeckt Mixed-greediness reguläre Ausdrücke - eine korrekte Implementierung unabhängige Definition dessen , was mixed-greediness regulären Ausdrücken entsprechen sollte - - und lässt sie "machen, was die Leute erwarten". Ich habe es versucht. Ich versuche es immer noch. Bisher kein Glück ...
Auswechslung
Der Befehl regsub wird für das Abgleichen und Ersetzen von regulären Ausdrücken verwendet.
set mydata {The yellow dog has the blues.}
# create a new string; only the first match is replaced.
set newdata [regsub {(yellow|blue)} $mydata green]
puts $newdata
The green dog has the blues.
# replace the data in the same string; all matches are replaced
regsub -all {(yellow|blue)} $mydata red mydata
puts $mydata
The red dog has the reds.
# another way to create a new string
regsub {(yellow|blue)} $mydata red mynewdata
puts $mynewdata
The red dog has the blues.
Rückverweise verwenden, um übereinstimmende Daten zu referenzieren.
set mydata {The yellow dog has the blues.}
regsub {(yellow)} $mydata {"\1"} mydata
puts $mydata
The "yellow" dog has the blues.
Dokumentation: regsub re_syntax
Unterschiede zwischen dem RE-Motor von Tcl und anderen RE-Motoren.
- \ m: Anfang eines Wortes.
- \ M: Ende eines Wortes.
- \ y: Wortgrenze.
- \ Y: ein Punkt, der keine Wortgrenze ist.
- \ Z: stimmt mit dem Datenende überein.
Dokumentation: re_syntax
Eine literale Zeichenfolge mit einem regulären Ausdruck abgleichen
Manchmal müssen Sie einen literalen (Unter-) String mit einem regulären Ausdruck abgleichen, obwohl dieser Teilstring RE-Metazeichen enthält. Ja, es ist zwar möglich, Code zu schreiben, um entsprechende Backslashes einzufügen, um diese Funktion auszuführen (mithilfe von string map ). Es ist jedoch am einfachsten, das Muster mit ***= , wodurch die RE-Engine den Rest des Strings lediglich als wörtliche Zeichen behandelt Alle weiteren Metazeichen werden deaktiviert.
set sampleText "This is some text with \[brackets\] in it."
set searchFor {[brackets]}
if {[ regexp ***=$searchFor $sampleText ]} {
# This message will be printed
puts "Found it!"
}
Beachten Sie, dass dies auch bedeutet, dass Sie keinen der Anker verwenden können.