2010-09-22 14 views
5

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.

+0

Sembra primo '(. *?)' Sempre corrispondere alla stringa vuota. –

+1

Non sempre. Corrisponde a tutti i personaggi fino ai primi due punti. – CanSpice

risposta

11

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).

1

(.*?) 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>.

2

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.

9

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.

+1

È dannatamente pulito! –

3

È 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 
} 
+1

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. –