2012-04-24 10 views
6

The Ruby (1.9.3) la documentazione sembra implicare che la scansione è equivalente a = ~ se non che la scansioneruby ​​regex scansione contro = ~

  1. restituisce più corrispondenze, mentre = ~ restituisce solo la prima occorrenza, e
  2. scan restituisce i dati della corrispondenza, mentre = ~ restituisce l'indice.

Tuttavia, nel seguente esempio, i due metodi sembrano restituire risultati diversi per la stessa stringa ed espressione. Perché?

1.9.3p0 :002 > str = "Perl and Python - the two languages" 
=> "Perl and Python - the two languages" 
1.9.3p0 :008 > exp = /P(erl|ython)/ 
=> /P(erl|ython)/ 
1.9.3p0 :009 > str =~ exp 
=> 0 
1.9.3p0 :010 > str.scan exp 
=> [["erl"], ["ython"]] 

Se l'indice del primo match è 0, non si deve eseguire la scansione di ritorno "Perl" e "Python" invece di "Erl" e "python"?

Grazie

risposta

12

Quando somministrato un'espressione regolare senza gruppi di cattura, scan restituirà un array di stringhe, dove ogni stringa rappresenta una corrispondenza dell'espressione regolare. Se usi scan(/P(?:erl|ython)/) (che è uguale alla tua regex tranne che senza gruppi di acquisizione), otterrai ["Perl", "Python"], che è quello che ti aspetti.

Tuttavia, quando viene assegnata un'espressione regolare con i gruppi di cattura, scan restituirà una matrice di matrici, in cui ogni sottoscheda contiene le acquisizioni di una determinata corrispondenza. Quindi, se si ha per esempio la regex (\w*):(\w*), si otterrà una matrice di matrici in cui ogni sub-array contiene due stringhe: la parte prima dei due punti e la parte dopo i due punti. E nel tuo esempio ogni sotto-array contiene una stringa: la parte corrispondente a (erl|ython).

+0

Grazie, quindi la scansione non è strettamente equivalente a = ~, quando ci sono gruppi coinvolti? – Anand

+2

@Anand Poiché la scansione restituisce qualcosa di completamente diverso da = ~, non penso sia mai esatto affermare che sono equivalenti. Il primo risultato restituito dalla scansione sarà una sottostringa che inizia all'indice 'str = ~ exp' se e solo se' exp' non contiene gruppi di cattura. In aggiunta a ciò si può anche dire che il primo risultato sarà equivalente a 'Regexp.last_match.string' dopo l'esecuzione di' str = ~ exp' se non contiene gruppi di cattura e 'Regexp.last_match.captures' se contiene gruppi di cattura. – sepp2k

+0

Felice di vedere questo tipo di post che puoi davvero imparare. – texasbruce