Hay funciones en Perl que se comportan de forma distinta según se estén ejecutando en contexto escalar o de lista. Es el caso de las expresiones regulares.
Si una expresión regular la ejecutamos en contexto escalar, nos devolverá
verdadero o
falso según el resultado de la búsqueda o coincidencia con el patrón. Por eso podemos usar expresiones regulares en while() e if() y en otros sitios donde sólo nos interesa saber si hay coincidencia con el patrón o no.
Using perl Syntax Highlighting
if ( $fichero =~ /^.+?[.]rar$/i ) {
say
"$fichero es un archivo RAR";
}Coloreado en 0.001 segundos, usando
GeSHi 1.0.8.4
En cambio, si una expresión regular la ejecutamos en contexto de lista, nos devolverá una lista (obviamente) de todos los subpatrones capturados por los paréntesis. Si no es capaz de capturar nada o no hay coincidencia con el patrón, devuelve una lista vacía.
Using perl Syntax Highlighting
my $fichero = "fichero.rar datos.rar cosas.rar";
my @archivos = $fichero =~ /(\w+)[.]rar/gi;
say
"[@archivos]"; # [fichero datos cosas]Coloreado en 0.001 segundos, usando
GeSHi 1.0.8.4
En principio, todo se ejecuta en contexto escalar, pero si Perl ve "algo" distinto, lo ejecutará en contexto de lista. Si lo que hay en la parte izquierda de la asignación es algo que se parece a un contenedor de elementos, entonces es que el usuario espera una lista de valores. Además,
y esto es importante, hemos puesto la opción '/g' a la expresión regular. Esa opción indica que queremos que el patrón se pruebe a lo largo de toda la variable $fichero, no que solo capture el primero que encuentre.
Y ahí es donde aparece el tema de los paréntesis.
Normalmente, ponemos una variable array en el lado izquierdo, así que los valores se van almacenando allí (como el caso del último ejemplo con @archivos). Pero también puede haber un par de paréntesis. Ejemplo:
Using perl Syntax Highlighting
my (undef, $segundo, undef) = $fichero =~ /(\w+)[.]rar/gi;
say
"[$segundo]"; # datosColoreado en 0.001 segundos, usando
GeSHi 1.0.8.4
En tu programa, al poner '($nombre)' ya estás indicando que quieres quedarte con el valor capturado por la expresión regular. Solo un valor, además, ya que la exp. reg. no tiene '/g'.
En la segunda línea, pasa lo mismo con '@nombres'. En este caso, estas solicitando todos los valores posibles que la exp. reg. pueda encontrar, pero ésta no tiene la opción '/g', así que solo devolverá la primera captura.
De hecho, las dos líneas devuelven el mismo valor, porque el patrón así lo indica: los paréntesis deben capturar todo lo que hay (
(.+)) entre el principio (
^) de la cadena de caracteres hasta el ".rar" del final (
$).
Es posible que no sea eso lo que quieres hacer, sino capturar cada nombre de archivo por separado:
Using perl Syntax Highlighting
my @archivos = $fichero =~ /(\w+[.]rar)/gi; # [fichero.rar datos.rar cosas.rar]Coloreado en 0.001 segundos, usando
GeSHi 1.0.8.4
Por último, una lindeza de lo que se puede hacer...
Using perl Syntax Highlighting
my $numero_nombres = () = $fichero =~ /(\w+[.]rar)/gi; # 3Coloreado en 0.001 segundos, usando
GeSHi 1.0.8.4
Perl está viendo que la expresión regular se debe ejecutar en contexto de lista, debido a la presencia de los paréntesis. Perl busca todas las capturas posibles, por la presencia de la opción '/g'. Luego toma todos esos valores y los intenta meter en... ningún sitio (no hay nada dentro de los paréntesis). Pero, además, Perl ve que en el lado izquierdo hay otra asignación, esta vez en contexto escalar. Y ya sabemos qué pasa cuando una lista o array se ejecuta en contexto escalar: obtenemos el número de elementos. Así que ese valor es lo que al final se almacena en la primera variable.
Más información en la sección "
Operadores regex entrecomillados", de
perlop (busca por la subsección "
Coincidencia en contexto de lista").