tcl
Normale uitdrukkingen
Zoeken…
Syntaxis
- regexp? schakelaars? exp string? matchVar? ? subMatchVar subMatchVar ...?
- regsub? schakelaars? exp string subSpec? varName?
Opmerkingen
Dit onderwerp is niet bedoeld om reguliere expressies zelf te bespreken. Er zijn veel bronnen op internet met uitleg over reguliere expressies en hulpmiddelen voor het maken van reguliere expressies.
In dit onderwerp worden de algemene schakelopties en methoden voor het gebruik van reguliere expressies in Tcl en enkele van de verschillen tussen Tcl en andere reguliere expressie-engines besproken.
Reguliere expressies zijn over het algemeen traag. De eerste vraag die u moet stellen is: "Heb ik echt een reguliere expressie nodig?". Pas alleen aan wat u wilt. Als u de andere gegevens niet nodig hebt, pas deze dan niet aan.
Voor deze reguliere expressievoorbeelden wordt de -uitbreidingsschakelaar gebruikt om de reguliere expressie te kunnen becommentariëren en toelichten.
Bij elkaar passen
De opdracht regexp wordt gebruikt om een reguliere expressie te vergelijken met een tekenreeks.
# 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]
De opdracht regexp retourneert een 1 (true) -waarde als een match is gemaakt of 0 (false) als dat niet het geval is.
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"
}
Om alle uitdrukkingen in sommige gegevens te matchen, gebruikt u de schakelaar -all en de -inline om de gegevens te retourneren. Merk op dat de standaard is om nieuwe regels te behandelen als andere gegevens.
# 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 afhandeling
# 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 vereist geen speciale afhandeling.
% set mydata {123ÂÃÄÈ456}
123ÂÃÄÈ456
% regexp {[[:alpha:]]+} $mydata match
1
% puts $match
ÂÃÄÈ
% regexp {\w+} $mydata match
1
% puts $match
123ÂÃÄÈ456
Documentatie: regexp re_syntax
Gulzige en niet-hebzuchtige kwantificatoren combineren
Als je een hebzuchtige overeenkomst als eerste kwantificator hebt, is de hele RE hebzuchtig,
Als je een niet-hebzuchtige overeenkomst als eerste kwantificator hebt, is de hele RE niet-hebzuchtig.
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
In het eerste geval is de eerste \ w + hebzuchtig, dus alle kwantificatoren zijn gemarkeerd als hebzuchtig en de. *? komt meer overeen dan verwacht.
In het tweede geval, het eerste. *? is niet-hebzuchtig en alle kwantificatoren zijn gemarkeerd als niet-hebzuchtig.
Andere reguliere expressie-engines hebben misschien geen probleem met hebzuchtige / niet-hebzuchtige kwantificatoren, maar ze zijn veel langzamer.
Henry Spencer schreef : ... Het probleem is dat het heel, heel moeilijk is om een generalisatie van die verklaringen te schrijven die reguliere uitdrukkingen van gemengde hebzucht omvat - een juiste, implementatie-onafhankelijke definitie van wat reguliere uitdrukkingen van gemengde hebzucht moeten matchen - - en laat ze doen "wat mensen verwachten". Ik heb geprobeerd. Ik probeer het nog steeds. Tot nu toe geen geluk. ...
vervanging
De regsub opdracht wordt gebruikt voor het matchen van reguliere expressies en vervanging.
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.
Terugverwijzingen gebruiken om naar overeenkomende gegevens te verwijzen.
set mydata {The yellow dog has the blues.}
regsub {(yellow)} $mydata {"\1"} mydata
puts $mydata
The "yellow" dog has the blues.
Documentatie: regsub re_syntax
Verschillen tussen de RE-motor van Tcl en andere RE-motoren.
- \ m: Begin van een woord.
- \ M: Einde van een woord.
- \ y: Woordgrens.
- \ Y: een punt dat geen woordgrens is.
- \ Z: komt overeen met het einde van de gegevens.
Documentatie: re_syntax
Een letterlijke tekenreeks koppelen aan een reguliere expressie
Soms moet je een letterlijke (sub-) string koppelen aan een reguliere expressie, ondanks die substring die RE-metatekens bevat. Hoewel ja, het is mogelijk om code te schrijven om geschikte backslashes in te voegen om dat te laten werken (met behulp van string map ), het is het gemakkelijkst om het patroon gewoon voor te laten gaan door ***= , waardoor de RE-engine de rest van de string als alleen letterlijke tekens behandelt , waarbij alle verdere metatekens worden uitgeschakeld.
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!"
}
Merk op dat dit ook betekent dat u geen van de ankers kunt gebruiken.