Estoy editando un archivo Perl, pero no entiendo esta comparación de expresiones regulares. ¿Puede alguien explicarmelo?
if ($lines =~ m/(.*?):(.*?)$/g) { } ..
¿Qué ocurre aquí? $lines
es una línea de un archivo de texto.
Estoy editando un archivo Perl, pero no entiendo esta comparación de expresiones regulares. ¿Puede alguien explicarmelo?
if ($lines =~ m/(.*?):(.*?)$/g) { } ..
¿Qué ocurre aquí? $lines
es una línea de un archivo de texto.
dividirla en partes:
$lines =~ m/ (.*?) # Match any character (except newlines)
# zero or more times, not greedily, and
# stick the results in $1.
: # Match a colon.
(.*?) # Match any character (except newlines)
# zero or more times, not greedily, and
# stick the results in $2.
$ # Match the end of the line.
/gx;
lo tanto, esto coincidirá con cadenas como ":"
(que coincide con cero caracteres, luego dos puntos, entonces cero caracteres antes del final de la línea, $1
y $2
están vacías cadenas) o "abc:"
($1 = "abc"
, $2
es una cadena vacía) o "abc:def:ghi"
($1 = "abc"
y $2 = "def:ghi"
).
Y si pasa una línea que no coincide (parece que esto sería si la cadena no contiene dos puntos), entonces no procesará el código que está entre corchetes. Pero si coincide, el código entre corchetes puede usar y procesar las variables especiales $1
y $2
(al menos, hasta que aparezca la siguiente expresión regular, si hay una dentro de los corchetes).
(.*?)
captura cualquier carácter, pero el menor número de ellos posible.
Por lo tanto, busca patrones como <something>:<somethingelse><end of line>
, y si hay múltiples :
en la cadena, la primera de ellas se utilizará como el divisor entre <something>
y <somethingelse>
.
Esa línea dice que se realice una coincidencia de expresiones regulares en $lines
con la expresión regular m/(.*?):(.*?)$/g
. Devolverá efectivamente true
si se puede encontrar una coincidencia en $lines
y false
si no se puede encontrar uno.
Una explicación del operador =~
:
binario "= ~" se une una expresión escalar a una coincidencia de patrón. Determinadas operaciones buscan o modifican la cadena $ _ por por defecto. Este operador hace que ese tipo de operación funcione en alguna otra cadena . El argumento correcto es un patrón de búsqueda , sustitución o transliteración. El argumento de la izquierda es lo que se supone que debe buscarse, sustituido o transcrito en su lugar del valor predeterminado $ _. Cuando se utiliza en contexto escalar , el valor de retorno generalmente indica el éxito de la operación .
la expresión regular en sí es:
m/ #Perform a "match" operation
(.*?) #Match zero or more repetitions of any characters, but match as few as possible (ungreedy)
: #Match a literal colon character
(.*?) #Match zero or more repetitions of any characters, but match as few as possible (ungreedy)
$ #Match the end of string
/g #Perform the regex globally (find all occurrences in $line)
Así que si $lines
partidos contra esa expresión regular, que entrarán en la parte condicional, de lo contrario será false
y lo saltará.
Hay una herramienta para ayudar a comprender las expresiones regulares: YAPE::Regex::Explain.
Ignorando el modificador g
, lo que no se necesita aquí:
use strict;
use warnings;
use YAPE::Regex::Explain;
my $re = qr/(.*?):(.*?)$/;
print YAPE::Regex::Explain->new($re)->explain();
__END__
The regular expression:
(?-imsx:(.*?):(.*?)$)
matches as follows:
NODE EXPLANATION
----------------------------------------------------------------------
(?-imsx: group, but do not capture (case-sensitive)
(with^and $ matching normally) (with . not
matching \n) (matching whitespace and #
normally):
----------------------------------------------------------------------
( group and capture to \1:
----------------------------------------------------------------------
.*? any character except \n (0 or more times
(matching the least amount possible))
----------------------------------------------------------------------
) end of \1
----------------------------------------------------------------------
: ':'
----------------------------------------------------------------------
( group and capture to \2:
----------------------------------------------------------------------
.*? any character except \n (0 or more times
(matching the least amount possible))
----------------------------------------------------------------------
) end of \2
----------------------------------------------------------------------
$ before an optional \n, and the end of the
string
----------------------------------------------------------------------
) end of grouping
----------------------------------------------------------------------
Ver también perldoc perlre.
¡Eso es condenadamente limpio! –
Fue escrito por alguien que sabe demasiado sobre expresiones regulares o no lo suficiente sobre las variables $'
y $`.
esto podría haber sido escrita como
if ($lines =~ /:/) {
... # use $` ($PREMATCH) instead of $1
... # use $' ($POSTMATCH) instead of $2
}
o
if (($var1,$var2) = split /:/, $lines, 2 and defined($var2)) {
... # use $var1, $var2 instead of $1,$2
}
Si desea usar /: /, use la bandera/p y las variables $ {^ PREMATCH} y $ {^ POSTMATCH} de Perl 5.10. Preferiría una división, sin embargo, ya que eso es lo que realmente está sucediendo. –
Parece que los primeros '(. *?) 'Coincidirá siempre con cadena vacía. –
No siempre. Coincidirá con todos los personajes hasta los primeros dos puntos. – CanSpice