La forma en que se usan en Perl es muy similar a la que utiliza el comando grep de Unix. Dicho comando se suele utilizar para buscar en los ficheros de entrada (o bien en la entrada estándar) las líneas que contienen un patrón especificado.
Desde la línea de órdenes llamamos al comando grep con la opción -e para indicarle la expresión regular que queremos utilizar, y justo después le indicamos los ficheros donde queremos buscar esa expresión regular. Por ejemplo:
$ grep -e "grep\|Unix" *.txtnos buscará en los ficheros con extensión .txt del directorio donde estamos en ese momento cualquier línea que contenga las cadenas grep o Unix.
Como fichero de ejemplo, todos utilizaremos el mismo, cuyo contenido es el que aparece a continuación:
Esto es simplemente un fichero de texto normalito, para hacer pruebas con el comando grep del Unix. Para hacer recuentos de cadenas y todo eso teniendo en cuenta las mayusculas y minusculas (Unix UnIx uNiX gReP y todo eso...
Entre las muchas opciones del comando, podemos especificarle que no nos imprima las líneas donde ha encontrado el patrón, sino que nos imprima el número de veces que se cumple dicho patrón. Así, el siguiente ejemplo
$ grep -c -e "grep\|Unix" *.txtcuenta el número de veces que cada fichero cumple ese patrón. Un ejemplo de salida obtenida sería:
3
Otra opción interesante es la posibilidad de indicarle que no haga distinciones entre mayúsculas y minúsculas, usando la opción -i. Así, no hará distinción entre Unix o uNiX, por ejemplo. Veamoslo con un ejemplo:
$ grep -c -e "grep\|Unix" *.txt
6
Otra opción interesante es que nos indique la línea en la que se produjo la coincidencia entre el patrón y la línea del fichero. Esto lo podemos conseguir con la opción -n.
$ grep -n -e "grep\|Unix" *.txt
Por último, a veces nos interesa especificar una expresión regular que no queremos que se cumpla. Eso lo podemos hacer con la opción -v.
$ grep -v -c -e "grep\|Unix" *.txt 9
Además de las alternativas en la expresión regular, especificada con el caracter |, podemos especificar rangos de caracteres, utilizando los corchetes ([ ]); un caracter cualquiera utilizando el punto (.); que cierto sub-patrón aparezca como mucho una vez (?) o que aparezca cero o mas veces (*) o que aparezca una o mas veces (+); etc, etc.
Para utilizarlas, las debemos encerrar entre // (mientras que en grep se colocaban indicadas con -e y entre comillas). Normalmente devolverán un valor lógico indicando si la variable sobre la que queremos aplicarla contiene o no el patrón. Si no se indica otra cosa, por defecto comparará la expresión con la variable "por defecto" $_. Por ejemplo:
/pepe/devolverá el valor cierto si $_ contiene la cadena pepe.
El programa:
$_ = "hola pepe"; print "si\n" if (/pepe/);imprimirá si, ya que la expresión regular devulve el valor lógico de verdadero.
Si queremos utilizar otra variable diferente a la $_ debemos utilizar el operador =~ , por ejemplo:
$cad =~ /pepe/es cierto si la cadena pepe esta incluida en $cad
Las expresiones regulares son sensitivas a mayúsculas, así, la expresión:
$cad = "Pepe come queso"; $cad =~ /pepe/;es falsa, ya que $cad no contiene la subcadena pepe, aunque contenga la subcadena Pepe.
El operador que hace lo contrario que el =~ es el !~ , así, la expresión:
$cad = "Pepe come queso"; $cad !~ /pepe/;es cierta.
. | cualquier caracter salvo el de retorno de carro |
---|---|
^ | indica que coincida al principio de la línea |
$ | indica que coincida al final de la línea |
* | aparezca 0 o más veces el caracter que lo precede |
+ | aparezca 1 o más veces el caracter que lo precede |
? | aparezca 0 o 1 veces el caracter que lo precede |
[] | indica un conjunto de caracteres que pueden aparecer |
[^] | indica un conjunto de caracteres que no pueden aparecer |
| | indica una disyunción, aparezca una de las opciones |
() | agrupa una serie de patrones en un simple elemento |
{n} | que coincida exactamente n veces |
{n,} | que coincida al menos n veces |
{n,m} | que coincida al menos n veces y no mas de m |
\n | un retorno de línea |
\t | un tabulador |
\w | un caracter alfanumérico (equivale a [a-zA-Z0-9_]) |
\W | un caracter no alfanumérico (equivale a [^a-zA-Z0-9_]) |
\d | un caracter numérico (equivale a [0-9]) |
\D | un caracter no numérico (equivale a [^0-9]) |
\s | un caracter de espaciado (espacio, tabulador, nueva línea, etc) |
\S | un caracter NO de espaciado |
\b | coincida con los límites de una palabra |
\B | coincida con el interior de una palabra |
\033 | un número octal (el 033) |
\x1b | un número hexadecimal (el 1B) |
\| \[ \] \( \) \* \^ \/ \\ etc | representan | [ ] ( ) * / \ (hay que escapar estos caracteres especiales) |
d.l | una "d" seguida de un caracter cualquiera y una "l" (del, dal, dzl, d5l, etc) |
---|---|
^f | una "f" al principio de la cadena (fofo, farfolla, f35, etc) |
^hol | "hola" al principio de la cadena (hola, holita, etc) |
e$ | una "e" al final de la cadena (este, ese, etc) |
te$ | "te" al final de la cadena (este, paquete, etc) |
ind* | "in" seguido de cero o más caracteres "d" (in, ind, indd, etc) |
.* | cualquier cadena, sin retorno de carro |
^$ | una cadena vacia |
[qjk] | una "q", o una "j" o una "k" |
[^qjk] | no sea "q", o una "j" o una "k" |
[a-z] | cualquier letra entre la "a" y la "z" |
[^a-z] | no sean letras minúsculas |
[a-zA-Z] | una letra minúscula o mayúscula |
[a-z]+ | una secuencia no vacia de letras minúsculas |
f.*ca | coincide con p.e. "fca", "foca", "flaca", "flor vaca", etc |
f.+ca | coincide con los anteriores salvo con "fca" |
fe?a | coincide con "fa" y "fea" |
^[ \t]*$ | una linea en blanco, o combinaciones de espacios y tabuladores |
[-+]?\d*\.?\d* | lo mismo que [-+]?[0-9]*\.?[0-9]* (números decimales) |
( (\d{1,2})\/(\d{1,2})\/(\d{1,4}) ) | una fecha en el siguiente formato DD/MM/AAAA (13/02/1674 ó 8/2/23 pero también 99/99/9999) |
pepe|juan | o "pepe" o "juan" |
(pe|hue)cos | o "pecos" o "huecos" |
(da)+ | o da o dada o dadada ... |
[01] | un "0" o un "1" |
\/0 | una división por 0 |
\/ 0 | una división por 0 con un espacio |
\/\s0 | una división por 0 con un caracter de espacio (espacio, tabulador, retorno de carro) |
\/ *0 | una división por 0 con varios espacios |
\/\s*0 | una división por 0 con posibles caracteres de espaciado |
\/\s*0\.0* | una división por 0 con posibles caracteres espaciado y acepta "0." "0.0" "0.00" etc |
fia|fea|fua | coincida con "fia", "fea" o "fua" |
f(i|e|u)a | coincida con "fia", "fea" o "fua" |
(fia|fea|fua) | equivale a los dos anteriores |
[fia|fea|fua] | equivale a [fiaeu] |
Los dos últimos ejemplos nos muestran que debemos ir con cuidado a la hora de colocar las alternativas en las expresiones regulares. Se suelen usar los paréntesis para encerrar las alternativas en las expresiones regulares y para agrupar patrones a recordar para después, mientras que se usan los corchetes para especificar clases.
A veces nos convendrá utilizar el contenido de una variable dentro de la expresión regular. Así, dependiendo del valor de esa variable podemos buscar diversos patrones (por ejemplo, buscar el contenido de la variable $a dentro de la variable $b).
Pues bien, podemos hacer uso de las variables dentro de las expresiones regulares directamente, como se ve en el siguiente ejemplo:
#!/usr/bin/perl $a = <>; $b = <>; chop($a); chop($b); if( $b =~ /$a/ ) { print "$a esta incluida en $b \n"; }este programa lee de entrada estándar dos cadenas y comprueba si la primera está incluida en la segunda.
Pero se plantea un problema... ¿y si la expresión regular es algo más compleja? Supongamos que queremos comprobar si $a seguida de una "P" se encuentra en $b. En este caso no podemos poner if( $b =~ /$aP/ ) { porque Perl intentaría buscar en $b el contenido de la variable $aP, y no el de la variable $a seguida de una "P". En este caso hay que hacer algo como if( $b =~ /${a}P/ ) { (nótese el uso de las llaves rodeando el nombre de la variable).
Además de identificar expresiones regulares, Perl puede hacer sustituciones basadas en los "emparejamientos" identificados en las expresiones. La forma de hacer eso es con la función s///.
Para hacer una sustitución de loco por Loco en la cadena $cad, usamos:
$cad =~ s/loco/Loco/;y para hacerlo en la cadena $_:
s/loco/Loco/;
$cad =~ s/loco/Loco/g;La expresion retorna el número de sustituciones hechas, 0 (falso) o mayor que 0 (verdadero).
Si queremos replazar ocurrencias como lOco, lOcO, LoCo, etc por Loco, podemos hacer:
$cad =~ s/[Ll][Oo][Cc][Oo]/Loco/g;o más fácil, utilizamos la opcion i (de ignorar mayúsculas):
$cad =~ s/loco/Loco/gi;y hace una sustitución global e ignorando las mayúsculas.
Si lo que queremos es evaluar algo, en la segunda parte de la expresión regular, debemos utilizar la opción e.
En el siguiente ejemplo, se lee de entrada estándar (sobre $_) y para cada línea (se supone que tiene un número real, ¡con su punto y todo!) se realiza una operación matemática, quedando el resultado almacenado en $_. En este ejemplo se hace uso de una variable especial $& que "recuerda" cierta parte del patrón correspondiente a una parte de la expresión regular que hayamos encerrado entre paréntesis.
while(<>) { s/(\d+\.\d+)/$&*100/e; print; }
Para hacer una translación utilizamos la función tr///. Así, la siguiente expresión reemplaza cada "a" por "e", cada "b" por "d" y cada "c" por "f" en la cadena $cad:
$cad =~ tr/abc/edf/;la expresión retorna el número de sustituciones hechas.
El siguiente ejemplo cuenta el número de asteriscos en la cadena $cad:
$contador = ( $cad =~ tr/*/*/ );
El siguiente ejemplo transforma a mayúsculas la cadena $_:
tr/a-z/A-Z/;
A veces, en una expresión regular conviene recordar los patrones encontrados para ser usados posteriormente (en la expresión o fuera de ella). Esto se consigue, encerrando los patrones a recordar entre paréntesis y referenciándolos mediante las variables $1, $2, ... $9 (de sólo lectura) fuera de la expresión, o con las variables \1, \2, ... \9 dentro de la expresión.
Por ejemplo, el siguiente programa, sustituye las letras mayúsculas por dichas letras pero entre asteriscos:
$_ = "Hola Don Pepe"; s/([A-Z])/\*\1\*/g; print "$_"; Resultado: *H*ola *D*on *P*epe
En el siguiente ejemplo utilizamos los patrones encontrados fuera de la expresión regular, mediante la variable $1 para encontrar las palabras repetidas:
if( /(\b.+\b) \1/ ) { print "encontrada la palabra $1 \n"; }
El siguiente ejemplo intercambia el primer y último caracteres de la cadena $_:
s/^(.)(.*)(.)$/\3\2\1/;
El siguiente ejemplo intercambia las dos primeras palabras de la cadena $_:
$_ = "Hola Don Pepe"; s/^([^ ]*) *([^ ]*)/\2 \1/; print "$_"; Resultado: Don Hola Pepe
Tras el uso de una expresión regular, podemos utilizar las variables especiales $`, $&, $', (las tildes esas son las que están junto con la [ y con la {) que guardan lo que hay antes, lo encontrado y lo que hay después en la cadena:
$_ = "Hola Don Pepe"; /on/; print "\n $` \n $& \n $' \n"; Resultado: Hola D on Pepe