Version 2.1, Lunes 14 de Abril de 1997Tabla de contenidos
Seccion 3.4- Expresiones Regulares
3.4.1- Símbolos Normales
3.4.1.1- Individuales
3.4.1.2- Genéricos
3.4.2- Símbolos Especiales
3.4.3- Uso de Expresiones regulares
.
3.4.3.1- Búsqueda
3.4.3.2- Substitución
3.4.4- Variables
3.4.4.1- Variables de entrada
3.4.4.2- Variables de salida
Una de las características mas útiles de Perl es el proceso que da a sus escalares. Y las cadenas de caracteres reciven especial atención.3.4- Expresiones Regulares
Símbolo- Es un elemento, único y distinguible de cualquier otro, para Perl son caracteres
(especiales y normales) y en lo sucesivo usaremos los términos caracter y
símbolo indistintamente,
Cadena Es una serie finita de caracteres.
Lenguaje Es un conjunto de cadenas.
Expresión regular Es la descripción abstracta de un lenguaje, en forma de una cadena.
Lenguaje Regular Es aquel lenguaje que puede ser descrito mediante expresiones regualres.
Aunque esto puede resultar un tanto complejo, la idea central es simple, mediante un conjunto de símbolos
describiremos grupos de cadenas, a los que llamamos lenguajes, las descripciones, no son sino series de
símbolos, por lo que a fin de cuentas son también cadenas, pero para evitar confusiones les
llamaremos expresiones regulares.
Nota: No todos los conjuntos imaginables de cadenas son describibles por lenguajes regualres, de
ahí surgen los lenguajes naturales y muchos ortos, pero el estudio de los lenguajes es una rama
fascinante pero compleja de la matemática moderna que no trataremos aquí.
A pesar de las promesas de complejidad, el manejo de cadenas regualres lejos de dificultar las cosas, las simplifica sobremanera, aunque suele restar legibilidad al programa, bueno, para contrarrestar esto, recomiendo colocar al menos un comentario por cada expresión regular (de mas de 5 caracteres) que se use.
Los símbolos que en Perl usaremos para construir nuestras expresiones regulares los dividiremos en dos grandes grupos; normales y especiales, los primeros simplemente representaran un caracter mientras que los segundos darán descripciones de cadenas formadas con esos símbolos.
Solo resta recordar que Perl determina las cadenas regualres como aquellas que se encuentran entre "/", de modo que /hola/ Será para Perl una cadena regular. Y a lo largo de este capitulo pondremos las cadenas regulares en el formato de Perl.
Los símbolos mas usuales para formar parte de nuestras cadenas son los alfabéticos (en mayúsculas y minúsculas) y los dígitos, y estos símbolos se colocan tal cual.3.4.1- Símbolos Normales
3.4.1.1- Individuales
por ejemplo:
/hola/
Esta expresión regular indica que las cadenas así referidas contienen los símbolos
"h", "o", "l", y "a" en ese estricto orden.
En matemáticas formales esta expresión daría origen a un lenguaje con una
única cadena "hola", pero en Perl, esta expresión regular genera un lenguaje que contiene
todas las cadenas que CONTIENEN "hola" en cualquier lugar en su interior. Nótese que Perl no
"genera" el lenguaje, pues eso a menudo es una tarea imposible, pero si reconoce a las cadenas que
pertenezcan al lenguaje.
Todo caracter que se desee incluir que no sea alfabético, o numérico, deberá anteponerse de un backslash "\" , así por ejemplo:
El lenguaje que reconozca todas las cadenas que contengan "656-31-74.34" se puede representar por la siguiente cadena regular:
/656\-31\-74\.34/
Además, se pueden reconocer, entre otros, los siguientes caracteres especiales:
| \s | Espacio en blanco |
| \t | Tabulador |
| \n | Vuelta de carro + Avance de línea |
| \r | Vuelta de carro |
| \0xx | Caracter octal xx (i.e. /\062/ para el caracter ASCII 50) |
| \xXX | Caracter Hexadecimal XX (i.e. /\x1B/ para el caracter 27) |
| \cX | Caracter Control+X (i.e. \cC para Ctrl-C) |
Además, es común que deseemos reconocer una serie de símbolos de algún tipo, entendiendo como tipo de caracter a un conjunto de caracteres, por ejemplo, podemos hablar de los caracteres alfabéticos, que el conjunto de los caracteres de la "a" a la "z" minúsculas y de la "A" a la "Z" (mayúsculas).3.4.1.2- Genéricos
Perl define los siguientes grupos de caracteres, además de que con símbolos especiales podemos emplear grupos arbitrarios.
| . | Cualquier caracter (acepta a cualquiera) |
| \w | Caracter de palabra (alfanumérico y "_") |
| \W | Caracter que no es de palabra (todos menos alfanuméricos o "_") |
| \d | Dígito (0 a 9) |
| \D | Caracter que no es Dígito (todos menos 0 al 9) |
Además, define como caracteres especiales, las siguientes condiciones (que en realidad no se refieren a ningún caracter).
| \b | Limite de una palabra |
| \A ^ | Principio de cadena (puede usarse indistintamente "^" o "\A" |
| \Z $ | Fin de línea |
La diferencia entre "\A" y "^" o de "\Z" y "$" es que las versiones con "\" se refieren exclusivamente al inicio o fin de la cadena, y las versiones con un único símbolo se refieren a las diversas líneas dentro de la cadena (si las hay), pero para que estas funcionen de esta forma deberemos usar la opción "/m" e la cadena regular. En casos convencionales son idénticas.
Además de los símbolos que representan caracteres o series de caracteres tenemos toda una familia de símbolos que representan características de las series de caracteres que ya hemos especificado.3.4.2- Símbolos Especiales
Siendo S un símbolo normal o genérico y E un símbolo especial:
| (SS) | Agrupa los símbolos |
| S|S | Alternación ( "a" o "b" => /a|b/ ) |
| [S] | Clase de caracteres ( puntuación => /[.,;:]/ ) |
| S* | Cero, una, dos o cualquier numero de veces |
| S+ | Una, dos, o cualquier numero de veces (pero al menos una vez) |
| S(n) | Exactamente n veces (i.e. /a(5)/ Será equivalente a /aaaaa/ ) |
| S(n,m) | Al menos n veces y no mas de m veces (i.e. /a(2,4)/ => /(aa)|(aaa)|(aaaa)/ ) |
| S? | cero o una vez |
| SE? | Modifica al símbolo especial para que no sea "acaparador" |
Estos, como podrá verse, son los mas poderosos ( y menos claros), por lo que a continuación damos una larga lista de ejemplos que emplean uno o varios de ellos.
Palabras:
/\w*/
Son simplemente, todos los caracteres alfanuméricos (y "_") que estén juntos.
Números (naturales)
/\d*/
Es una serie de dígitos simple y sencilla.
Números reales (positivos sin mas adornos)
/\d*\.\d*/
Nótese que el "." necesita ponerse como "\."
Por ejemplo, para reconocer los teléfonos que estén dados en alguno de los formatos:
###-##-## o ###-#### o #####-## o #######, no admitiendo nada antes o después:
/^\d(3)\-?\d(2)\-?d(2)$/
Lo que, en castellano seria:
Inicio de cadena, luego tres dígitos, uno o cero "-", dos dígitos, uno o cero "-", dos
dígitos y final de la cadena.
Para reconocer: Nombre Apellido Apellido, dando por hecho que Nombre y los Apellidos son
alfabéticos y están separados por espacios:
/\w*\s\w*\s\w*/
Nótese que encontrara al nombre aun si esta dentro de alguna cadena, por ejemplo "674.52.64
Daniel Sol Llaven. Tibet #32" pues la cadena regular descrita si esta presente y no requirió ni inicio
ni fin de cadena.
Para encontrar la primera palabra y otra palabra al final, en cualquier cadena:
/^.*?\w*.*?\w*$/
Traducido: Busca el inicio de la cadena, seguido de cualquier numero de caracteres cualesquiera, pero
siendo este el mínimo numero que no haga fallar la expresión, seguidos de cualquier numero
de caracteres de una palabra, seguidos de otra vez, cualquier numero mínimo de caracteres
cualesquiera, seguidos de cualquier numero de caracteres de palabra, seguidos del fin de línea.
No es evidente el que el patrón no realice la operación deseada sin los "?
", para ejemplificarlo, vemos el siguiente ejemplo:
para la cadena: "2342:Esta es la cadena que usamos para probar, si, esta"
con la expresión:
/^.*\w*.*\w*$/
De hecho encuentra la expresión una cadena del lengaje, pero la divide de modo incorrecto
(mas adelante veremos como usar las expresiones regualres para extraer segmentos de las cadenas,
ahora solo revisemos como se comportan los símbolos especiales).
usemos la siguiente leyenda para indicar a quien asocia cada parte de la cadena regular:
| ^ | inicio de la cadena, no la indicamos. |
| .* | "...." debajo de la parte que es reconocida por estos símbolos. |
| \w* | "11111" debajo de la primera palabra. |
| .* | "****" debajo de la segunda separación |
| \w* | "debajo de la segunda palabra (que esta al final de la cadena). |
| $ | Fin de la línea, no la indicamos. |
2342:Esta es la cadena que usamos para probar, si, esta
.....................................................12
Nótese que la primera serie "cualquier caracter de cero a cualquier numero" representada por "."
absorbe casi toda la cadena, esto es porque el "*" de la expresión regular es acaparador, y
tomara tantos caracteres como le sea posible sin que la expresión no sea reconocida. Se distingue
además que no hay una segunda serie de "cualesquiera caracteres" entre las dos palabras, esto es
porque el "*" permite desde cero hasta cualquier numero de caracteres, en esta ocasión,
toma la opción te adquirir cero caracteres.
Así pues, para que reconozca las palabras como deseamos, debemos hacer que las separaciones
no sean acaparadoras, es decir, tomen el mínimo numero de caracteres posible, para que dejen a
nuestras palabras los mas posibles. Para lograr esto, ponemos "?" a continuación de los
"*" que no deseamos sean acaparadores, resultando la expresión regular:
/^.*?\w*.*?\w*$/
Usando la misma leyenda para ilustrar como reconoce la cadena:
2342:Esta es la cadena que usamos para probar, si, esta
.....1111******************************************2222
Funciono como esperábamos esta vez, porque:
La primera secuencia de "cualesquiera caracteres" toma la mínima cantidad de caracteres que dejan
una palabra a continuación (para que la expresión no falle), luego, el "\w*"
toma todos los caracteres alfabéticos a su alcance (no hay "_") . La segunda parte ".*?
" toma el mínimo de caracteres que dejen a continuación una palabra Y que a
continuación de esta palabra este el fin de línea (esta condición del fin de
línea evita que termine por ejemplo en el "probar, " pues aunque si es una palabra lo que sigue,
no termina en un fin de línea, sino en espacio).
No permita el lector que la aparente complejidad, y patente obscuridad de estas expresiones lo asuste, en el ámbito de la programación real siempre hay tiempo de probar que las cadenas regulares que planteamos funcionen, y en su oportunidad, escribirlas mediante un método de auténtica "prueba y error".
Como mencionamos en la sección de operadores, los operadores principales para usar las expresiones regualres son s/// y m//, pero no ahondamos en los usos que les podemos dar, que no son ni mucho menos, tan patentes como los usos de los operadores convencionales.3.4.3- Uso de Expresiones regualres.
Por su utilidad, podemos dividir los principales usos de las expresiones regulares en tres categorías:
| Búsqueda | Donde el objetivo es verificar la existencia de un patrón en una cadena (ver si la cadena pertenece al lenguaje especificado). |
| Substitución | Reemplazar una cadena (o lenguaje) por otro, muy útil para modificar sistemáticamente una cadena en una serie de archivos (usando Perl en línea). |
| Extracción | También se pueden utilizar para extraer subcadenas que cumplan con ciertas características dentro de las cadenas que proporcionemos, que pertenezcan al lenguaje. |
Esta es por mucho la mas sencilla de las aplicaciones, simplemente verifica que una cadena cumpla con el lenguaje especificado y regresa un valor lógico para indicar el éxito o el fracaso de la cadena. El uso típico de esta función, es el elaborar una espacie de grep en Perl.3.4.3.1- Búsqueda
Pasando directamente a los ejemplos:
Si deseamos imprimir solamente las líneas de comentario de un programa en Perl, podríamos escribir el siguiente script.
#/usr/bin/perl
open(AE,"ARGV[0]"); #Abrimos para lectura el archivo dado como primer parámetro.
while($reng=<AE>)
{
if($reng=~m/^\#/) #Estrictamente las líneas que inicien con #
{
print $reng;
}
}
close(AE);
Como se puede ver, este script imprimirá todas las líneas del archivo original que inicien con
"#", esto ignora los comentarios al final de las líneas, pero este detalle se
correge con eliminar el "^" del inicio de la expresión regular.
Si deseamos hacer un demigrep, o supergrep (como se desee) que responda a la siguiente
invocación:
grep.pl archivo patrón, siendo el patrón una cadena regular, imprimiendo del archivo dado
como parámetro las líneas que cumplan con el.
#/usr/bin/Perl
open(AE,"ARGV[0]"); #Abrimos para lectura el archivo dado como primer parámetro.
while($reng=<AE>)
{
if($reng=~m/$ARGV[1]/) #En efecto, al igual que en las "" se substituyen las vairables entre //
{
print $reng;
}
}
close(AE);
La característica de formación dinámica de las cadenas regulares funciona tanto
para Perl4 como para Perl5. y puede ser de gran utilidad cuando el patrón que los renglones deben
cumplir depende de la información contenida en el mismo archivo. Esta característica la
revisamos a fondo en la sección 3.4.4.1
El uso mas común de las expresiones regualres es el cambiar una cadena por otra cuando así se requiere (dondequiera que este en la cadena original). con lo que se resumen grandes segmentos de código sobretodo en el filtrado de largos archivos de texto.3.4.3.2- Substitución
Esta función se basa en el operador s/// , su sintaxis es:
s/EXP1/EXP2/MOD
donde:
EXP1 Es la expresión que buscamos y que de encontrarla
será substituida
EXP2 Es la expresión por la que hemos de substituir la expresión
buscada
MOD Es un modificador de la operación del s/// usualmente "g"
Así como el modificador se agrega al final de s/// , se puede agregar al final de la expresión m// , para revisar los modificadores recomiendo que se consulte la referencia en el capitulo de operadores PERLOP y de cadenas regualres PERLRE.
El primer ejemplo, sea el comando de Perl en línea de comando que cambiaría en todos los programas .pl del directorio la ruta de Perl (tarea común cuando se migra un programa de una maquina a otra).
/usr/leng/Perl -pi.bak -e "s/\/usr\/bin\/perl/\/usr\/leng\/perl/g";
En resumen, lo que hace este comando es que todas las ocurrencias de "/usr/bin/Perl" (los / se anteceden de un \ para evitar que se confundan con el final de la expresión regular), sean reemplazadas por "/usr/leng/Perl" cuantas veces aparezcan en un renglón (esa es la función del modificador "g" que no solo se realice una substitución si hay mas de una ocurrencia en la misma cadena).
Las expresiones regulares se vuelven extremadamente poderosas al agregarles variables, estas aparecen tanto de entrada como de salida.3.4.4- Variables
Las variables de entrada son reemplazadas (como se reemplazan en las cadenas que están entre
comillas "") en las expresiones regulares, esto nos da la posibilidad de emplear cadenas regualres
determinadas en tiempo de corrida.
Las variables de salida son variables constantes (no podemos
modificar sus valores directamente) en las que se colocan las diversas coincidencias de las cadenas
regulares con la cadena de prueba, estas nos dan la posibilidad de extraer información de nuestras
cadenas de prueba en base a cadenas regulares.
Hasta ahora, las expresiones regualres a evaluar son constantes, esto es, entre ejecuciones del programa siempre buscamos el mismo lenguaje de la cadena de prueba. Esto es solo un caso particular para Perl, pues determina las expresiones regualres a evaluar en tiempo de corrida, lo que nos da la posibilidad de elaborar expresiones regulares que respondan a las necesidades de cada corrida.3.4.4.1- Variables de entrada
Por ejemplo:
$cadena="1321323palabra"; #Damos valor a la cadena de prueba
$cadena=~s/\w+//g"; #Le aplicamos la expresion regular \w+
Es funcionalmente equivalente a:
$cadena="1321323palabra"; #Damos valor a la cadena de prueba
$expresion="\w+";
#Una cadena que formará parte de la expresion regular
$cadena=~s/$expresion//g";#aplicamos la expresion regular a la cadena de prueba
Esto, porque en el segundo código, la expresión regular identifica a $expresion como una variable y substituye su valor en la expresión regular, en este caso \w* , de modo que ambos códigos reemplazaran las "palabras" (o grupos de caracteres alfabéticos contiguos) por la cadena vacía, quitando las "palabras" de la cadena de prueba $cadena.
A primera vista puede no ser muy evidente el uso de esta funcionalidad, pero nos permite diseñar los lenguajes que buscaremos en las cadenas sobre datos obtenidos en tiempo de corrida y actuar acorde a ellos.
Para ejemplificar esta funcionalidad, escribamos un segundo programa para cambiar la ruta al programa
de Perl en los propios programas de Perl (aunque no en el presente por supuesto, de modo que
habría que ejecutarlo pasando el programa como parámetro a Perl).
Pare esto requeriremos dos parámetros, la vieja ruta y la nueva ruta, y en ellos debemos hacer
una consideración especial, si tenemos:
$ruta1="/usr/bin/Perl";
$ruta2="/usr/leng/Perl";
$renglon=~s/$ruta1/$ruta2/g;
Al substituir las rutas en la expresión de substitución obtendríamos un código equivalente al siguiente:
$renglon=~s//usr/bin/perl//usr/leng/perl/g;
Que es erróneo!!!!
Como se puede apreciar, no colocamos los \ antes de los / de modo que los
/ de las rutas serían interpretados como delimitadores de la cadena regular.
Para corregir este problema existen dos posibles soluciones, uno, emplear algún otro caracter en lugrar de / para delimitar las expresiones regulares, pero por claridad y potencial fallo en caso de que algún posible valor de las variables empleara este nuevo caracter prefiero no emplearlo, para ver como opera recomiendo consultar la referencia en la sección del operador s///.
La segunda posibilidad, que es la que empleamos en el primer script de este propósito que
hicimos (en la sección 3.4.3.1) es el colocar \ antes de
cada / en la expresión regular de modo que no haya confusión en los limites
de nuestra expresión.
Esto podríamos hacerlo con expresiones regulares constantes, pero siendo una tarea muy
común, Perl ha implementado una función que realiza el trabajo por nosotros, esta
función es quotemeta, cuya sintaxis es:
quotemeta EXPRESIÓN
donde:
EXPRESIÓN es la expresión en la que antecederemos \ a cada caracter que pueda tener
alguna interpretación especial en algún tipo de cadena.
Debe notarse que si la empleáramos en una expresión como "\w*"
el resultado seria "\\w\*" de modo que seria completamente inocuo como expresión regular
(solo implicaría la secuencia literal de los tres caracteres "\","w" y
"*".
Sin embargo, para el ejemplo que nos ocupa es justo lo que necesitamos.
Además, para hacer mas breve el programa, hagámoslo operar solo sobre un archivo cuyo nombre (y ruta completa en caso de requerirlo) le pasamos como tercer parámetro.
Aclarado esto, pasemos al código.
#!/usr/bin/Perl
#Esta es una ruta tentativa, supongamos que es correcta o que eludimos usarla.
#recibimos en $ARGV[0] la ruta original
# y en $ARGV[1] la nueva ruta.
$ruta1=quotemeta($ARGV[0]);
$ruta2=$ARGV[1];
system("mv $ARGV[2] $ARGV[2].old");
open(PROG_OR,"<$ARGV[2].old");
open(PROG_N,">$ARGV[2]");
while($renglon=<PROG_OR>)
{
$renglon=~s/$ruta1/$ruta2/; #solo una substitución por renglón.
print PROG_N $renglon;
}
close PROG_OR;
close PROG_N;
Expliquemos ahora, por líneas el funcionamiento de este programa:
#!/usr/bin/Perl
#Esta es una ruta tentativa, supongamos que es correcta o que eludimos usarla.
#recivimos en $ARGV[0] la ruta original
#y en $ARGV[1] la nueva ruta.
Para fines prácticos, podemos considerar esto como un mero comentario inicial, pues no estamos seguros de que la posición de Perl sea esta, por lo que habrá de ejecutar este programa como Perl nombre del programa parametro1 parametro2 parametro3 ,nótese que requiere de Perl5.
$ruta1=quotemeta($ARGV[0]);
Esta instrucción copia el valor del primer argumento a la variable $ruta1, teniendo la precaución de colocar \ antes de todo caracter especial para que pueda ser empleado como expresión regular.
$ruta2=$ARGV[1];
El segundo parámetro lo copiamos tal cual, habrá que tener precaución al usarlo para que las / que contengan no interfieran, pero no podrá ser empleado como expresión regular.
system("mv $ARGV[2] $ARGV[2].old");
Movemos el archivo a editar a uno nuevo con el mismo nombre y la extensión ".old" a semejanza del script de la sección 3.4.3.1.
open(PROG_OR,"<$ARGV[2].old");
Abrimos como archivo de entrada el archivo original bajo su nuevo nombre.
open(PROG_N,">$ARGV[2]");
Y abrimos como archivo de salida un archivo recién creado con el nombre original del archivo a editar.
while($renglon=<PROG_OR>){
Iniciamos un ciclo típico para revisar todas las líneas del programa.
$renglon=~s/$ruta1/$ruta2/; #solo una substitución por renglón.
Realizamos la substitución, debe recordarse que solo la primera parte del operador s/// es una expresión regular, y la segunda es solo una cadena que se coloca en lugar de aquellas cadenas que correspondan con la expresión regular.
De modo que $ruta1 efectivamente es empleada como la expresión regular que
determina que cadena reemplazar, y $ruta2 solo especifica la cadena a poner en su lugar
(no es una expresión regular), como Perl sabe que $ruta2 es solo una cadena no es
necesario un manejo especial de esta, Esto no sería cierto si escribiesemos el valor de la
expresi&oacutre;n, pues no habría modo de saber cuales / son delimitadores.
Debe quedar bien claro que el operador s/// solo emplea una expresión regular que
es $ruta1, y que $ruta2 es una simple cadena que el operador emplea en la
substitución.
print PROG_N $renglon;}
Ultima instrucción del ciclo por línea, que imprime la línea ya trabajada por el operador s/// en el archivo de salida.
close PROG_OR;
close PROG_N;
Cerramos los archivos tanto de entrada como de salida al final del programa.
Como se ve, este es un programa muy sencillo, la mayor dificultad que tiene radica en comprender el uso que el operador da a sus operandos, y recomiendo que para una mayor claridad se consulte la referencia en la sección PERLOP en lo referente al operador s///.
Los usos que se le puedan dar a esta característica de las cadenas regualres quedan a la imaginación del programador, pero confío que en cuanto adquiera cierto dominio del lenguaje y se enfrente a problemas mas complejos hallara muchos y muy interesantes usos para esta característica y la siguiente.
Como he mencionado desde la sección 3.4.3 una de las características mas interesantes de las expresiones regulares es su capacidad de extraer información de las cadenas según su forma expresada en expresiones regualres.3.4.4.2- Variables de salida
El uso de las variables de salida es muy sencillo, cuando planteamos una expresión regular en la que existan paréntesis, las secciones de la cadena de prueba que correspondan con las sub-expresiones regulares contenidas en los paréntesis irán siendo colocadas en las variables $1, $2, $3, etc.
Así por ejemplo, para sacar la parte entera y fraccionaria de un numero como 4532431.243 probaríamos:
$numero="8942389.523";
$numero=~/(\d*)\.(\d*)/
$entero=$1;
$fraccion=$2;
expliquemos este ejemplo línea por línea:
$numero="8942389.523";
Creamos el numero a revisar, recordemos que las expresiones regualres trabajan sobre cadenas, así que a pesar de representar un valor numérico, ahorramos el paso de la conversión y la especificamos directamente como cadena.
$numero=~/(\d*)\.(\d*)/
Realizamos una búsqueda del expresión regular, la expresión regular traducida al castellano es:
busca una cadena de cero o mas dígitos y agrúpalos, luego, busca un punto y luego
busca un segundo grupo de cero o mas dígitos y agrúpalos.
Nótese que los dos grupos quedan indicados por las partes de la expresión regular que esta
entre paréntesis.
$entero=$1;
Aquí tomamos el valor de la variable constante $1, que contiene la parte de la cadena
de prueba que se verifico con el primer grupo de la expresión regular.
en este caso el valor en cuestión es "8942389"
$fraccion=$2;
Y después tomamos el valor del segundo grupo de la expresión regular y lo colocamos en la variable fracción, en este caso "523"
Debe notarse que en este ejemplo el "." no se incluyo en ninguno de los grupos, por lo que no figura en ninguna variable $1,$2, etc.
En este ejemplo el numero de grupos esta claramente definido desde el principio. Lo que no siempre es el caso, por ejemplo, supongamos que deseamos extraer los diversos elementos de un nombre e irlos imprimiendo uno por uno.
$nombre="David Jonathan Sol Llaven";
while($nombre =~ /(\w+)\s*/g)
{
print $1;
}
Debe notarse de este ejemplo que al emplear el modificador /g del operador m//
se van obteniendo las coincidencias una por una, en este caso, y el operador va recordando la
posición en que ocurrió la ultima ocurrencia para proseguir con la búsqueda en una
ocasión posterior, de no incluir el modificador /g cada nueva vuelta del ciclo while regresaría
el mismo elemento, el primero.
Una segunda opción, consisten en obtener el resultado de la expresión en su conjunto, este puede usarse en contexto escalar o en contexto de arreglo, este refinamiento es muy útil si deseamos, por ejemplo, obtener los elementos sacados de la cadena de prueba en grupos, sin embargo, la aplicación resulta un poco mas difícil de comprender y para no confundir los progresos logrados prefiero dejarlo a la investigación del lector.
Así pues, para comprender el funcionamiento de la obtención de los valores de una verificación de expresiones regulares recomiendo revisar la sección de operadores de la referencia, PERLOP, en lo concerniente al operador m// aunado con una saludable dosis de experimentación.
No olvide el lector que como casi cualquier otra característica de Perl, las expresiones regualres están ahí para facilitar las tareas a realizar, por lo que deben de emplearse para resumir largos procesos de búsqueda y separación de cadenas o para atacar problemas de revisión de cadenas.