Sto modificando un file Perl, ma non capisco questo confronto regexp. Qualcuno può spiegarmelo per favore?
if ($lines =~ m/(.*?):(.*?)$/g) { } ..
Cosa succede qui? $lines
è una linea da un file di testo.
Sto modificando un file Perl, ma non capisco questo confronto regexp. Qualcuno può spiegarmelo per favore?
if ($lines =~ m/(.*?):(.*?)$/g) { } ..
Cosa succede qui? $lines
è una linea da un file di testo.
suddividerlo in parti:
$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;
Quindi, questo corrisponderà stringhe come ":"
(che corrisponde a zero caratteri, quindi i due punti, poi zero caratteri prima della fine della linea, $1
e $2
sono vuoti stringhe) o "abc:"
($1 = "abc"
, $2
è una stringa vuota) o "abc:def:ghi"
($1 = "abc"
e $2 = "def:ghi"
).
E se si passa a una riga che non corrisponde (sembra che ciò avverrebbe se la stringa non contiene due punti), non elaborerà il codice compreso tra parentesi. Ma se corrisponde, il codice tra parentesi può usare ed elaborare le variabili speciali $1
e $2
(almeno, fino a quando non viene visualizzata la successiva espressione regolare, se ce n'è una tra parentesi).
(.*?)
acquisisce tutti i caratteri, ma il più piccolo possibile.
in modo che appaia come per i modelli <something>:<somethingelse><end of line>
, e se ci sono molteplici :
nella stringa, il primo verrà utilizzato come divisorio tra <something>
e <somethingelse>
.
Questa riga dice di eseguire una corrispondenza di espressioni regolari su $lines
con la regex m/(.*?):(.*?)$/g
. Restituirà efficacemente true
se è possibile trovare una corrispondenza in $lines
e false
se non è possibile trovarla.
Una spiegazione dell'operatore =~
:
Binary "= ~" lega un'espressione scalare ad un pattern match. Alcune operazioni cercano o modificano la stringa $ _ per il valore predefinito . Questo operatore esegue questo tipo di operazione su un'altra stringa . L'argomento giusto è una ricerca modello, sostituzione o traslitterazione . L'argomento di sinistra è quello che dovrebbe essere cercato, sostituito, o traslitterato invece del $ _ predefinito. Se utilizzato nel contesto scalare , il valore restituito in genere indica il successo dell'operazione .
L'espressione regolare è di per sé:
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)
Quindi, se $lines
partite contro che regex, si andrà nella parte condizionale, altrimenti sarà false
e dovrà saltare.
C'è uno strumento per aiutare a capire le espressioni regolari: YAPE::Regex::Explain.
Ignorando il g
modificatore, che non è necessario qui:
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
----------------------------------------------------------------------
Vedi anche perldoc perlre.
È dannatamente pulito! –
È stato scritto da qualcuno che sa troppo delle espressioni regolari o non abbastanza sulle variabili $'
e $`.
questo avrebbe potuto essere scritto come
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
}
Se si desidera utilizzare /: /, utilizzare il flag/p e le variabili $ {^ PREMATCH} e $ {^ POSTMATCH} da Perl 5.10. Preferirei dividere, poiché è quello che sta realmente accadendo. –
Sembra primo '(. *?)' Sempre corrispondere alla stringa vuota. –
Non sempre. Corrisponde a tutti i personaggi fino ai primi due punti. – CanSpice