tcl
Expresiones regulares
Buscar..
Sintaxis
- ¿Regexp? ¿Switches? ¿Cadena exp? matchVar? ? subMatchVar subMatchVar ...?
- ¿Regsub? ¿Switches? exp string subSpec? varName?
Observaciones
Este tema no pretende discutir las expresiones regulares en sí. Hay muchos recursos en Internet que explican expresiones regulares y herramientas para ayudar a construir expresiones regulares.
Este tema tratará de cubrir los conmutadores comunes y los métodos de uso de expresiones regulares en Tcl y algunas de las diferencias entre Tcl y otros motores de expresiones regulares.
Las expresiones regulares son generalmente lentas. La primera pregunta que debe hacer es "¿Realmente necesito una expresión regular?". Solo iguala lo que quieras. Si no necesita los otros datos, no los combine.
A los efectos de estos ejemplos de expresiones regulares, el interruptor expandido se utilizará para poder comentar y explicar la expresión regular.
Pareo
El comando regexp se usa para hacer coincidir una expresión regular con una cadena.
# 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]
El comando regexp devolverá un valor 1 (verdadero) si se realizó una coincidencia o 0 (falso) si no lo hizo.
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"
}
Para hacer coincidir todas las expresiones en algunos datos, use el interruptor -all y el interruptor -inline para devolver los datos. Tenga en cuenta que el valor predeterminado es tratar las líneas nuevas como cualquier otro dato.
# 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
Manejo de nueva linea
# 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 no requiere manejo especial.
% set mydata {123ÂÃÄÈ456}
123ÂÃÄÈ456
% regexp {[[:alpha:]]+} $mydata match
1
% puts $match
ÂÃÄÈ
% regexp {\w+} $mydata match
1
% puts $match
123ÂÃÄÈ456
Documentación: regexp re_syntax
Mezclando codificadores codificadores y no codiciosos
Si tiene una coincidencia codiciosa como el primer cuantificador, todo el RE será codicioso,
Si tiene una coincidencia no codiciosa como el primer cuantificador, el RE completo no será codicioso.
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
En el primer caso, el primer \ w + es codicioso, por lo que todos los cuantificadores se marcan como codiciosos y el. *? coincide más de lo esperado.
En el segundo caso, el primero. *? no es codicioso y todos los cuantificadores están marcados como no codiciosos.
Es posible que otros motores de expresión regular no tengan problemas con los cuantificadores codiciosos / no codiciosos, pero son mucho más lentos.
Henry Spencer escribió : ... El problema es que es muy, muy difícil escribir una generalización de esos estados que abarca las expresiones regulares mixto greediness - una definición adecuada, independiente de la implementación de lo que expresiones regulares mixto greediness deben coincidir - - Y les hace hacer "lo que la gente espera". He intentado. Todavía estoy intentando No hay suerte hasta ahora. ...
Sustitución
El comando regsub se utiliza para la coincidencia y sustitución de expresiones regulares.
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.
Uso de referencias inversas para hacer referencia a datos coincidentes.
set mydata {The yellow dog has the blues.}
regsub {(yellow)} $mydata {"\1"} mydata
puts $mydata
The "yellow" dog has the blues.
Documentación: regsub re_syntax
Diferencias entre el motor RE de Tcl y otros motores RE.
- \ m: principio de una palabra.
- \ M: Fin de una palabra.
- \ y: límite de la palabra.
- \ Y: un punto que no es un límite de palabra.
- \ Z: coincide con el final de los datos.
Documentación: re_syntax
Coincidencia de una cadena literal con una expresión regular
A veces es necesario hacer coincidir una cadena (sub) literal con una expresión regular a pesar de la subcadena que contiene metacaracteres RE. Mientras que sí, es posible escribir código para insertar barras diagonales apropiadas para hacer que funcione (usando el string map ) es más fácil simplemente prefijar el patrón con ***= , lo que hace que el motor de RE trate el resto de la cadena como solo caracteres literales , deshabilitando todos los metacaracteres adicionales.
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!"
}
Tenga en cuenta que esto también significa que no puede usar ninguno de los anclajes.