2013-05-16 37 views
16

Sono abbastanza sicuro che mi manca qualcosa di ovvio qui, ma non posso fare R per uso non avidi espressioni regolari:stringa non avido espressione regolare che corrisponde

> library(stringr) 
> str_match('xxx aaaab yyy', "a.*?b")           
    [,1] 
[1,] "aaaab" 

funzioni base si comportano allo stesso modo:

> regexpr('a.*?b', 'xxx aaaab yyy') 
[1] 5 
attr(,"match.length") 
[1] 5 
attr(,"useBytes") 
[1] TRUE 

mi aspetterei la partita di essere solo ab come da commento 'avidi' in http://stat.ethz.ch/R-manual/R-devel/library/base/html/regex.html:

Per impostazione predefinita la ripetizione è ingorda, quindi viene utilizzato il numero massimo possibile di ripetizioni. Questo può essere modificato in "minimo" aggiungendo? al quantificatore. (Ci sono ulteriori quantificatori che permettono di corrispondenza approssimativa: vedere la documentazione TRE.)

Qualcuno potrebbe spiegare che cosa sta succedendo?

Aggiornamento . Che cosa è folle è che in alcuni altri casi i modelli non avidi si comportano come previsto:

> str_match('xxx <a href="abc">link</a> yyy <h1>Header</h1>', '<a.*>') 
    [,1]           
[1,] "<a href=\"abc\">link</a> yyy <h1>Header</h1>" 
> str_match('xxx <a href="abc">link</a> yyy <h1>Header</h1>', '<a.*?>') 
    [,1]    
[1,] "<a href=\"abc\">" 

risposta

18

concetto difficile quindi farò del mio meglio ... Qualcuno si sente libero di modificarla e spiegare meglio se si tratta di un po 'di confusione .

Le espressioni corrispondenti ai modelli vengono cercate da sinistra a destra. Sì, tutte le stringhe seguenti aaaab, aaab, aab e ab corrispondono al modello, ma aaaab è quello che inizia più a sinistra è quello restituito.

Quindi qui, il tuo modello non-goloso non è molto utile. Forse questo altro esempio, vi aiuterà a capire meglio quando un modello di non-avido calci:

str_match('xxx aaaab yyy', "a.*?y") 
#  [,1]  
# [1,] "aaaab y" 

Ecco tutte le stringhe aaaab y, aaaab yy, aaaab yyy abbinati il ​​modello e ha iniziato nella stessa posizione, ma il primo era restituito a causa del modello non-goloso.


Quindi cosa si può fare per catturare l'ultimo ab? Usa questo:

str_match('xxx aaaab yyy', ".*(a.*b)") 
#  [,1]  [,2] 
# [1,] "xxx aaaab" "ab" 

Come funziona? Aggiungendo un modello avido .* nella parte anteriore, si sta forzando il processo per inserire l'ultimo a possibile nel gruppo catturato.

+0

Grazie @floder - Ho completamente dimenticato che inizia sempre la corrispondenza da sinistra. Le persone lo stanno discutendo da molto tempo: http://www.nntp.perl.org/group/perl.perl6.language.regex/2000/12/msg507.html –

3

Il problema è corrispondente alla finestra più breve tra due stringhe. @flodel indica correttamente che un motore regex sta analizzando la stringa da sinistra a destra, quindi tutte le corrispondenze sono più a sinistra. L'avidità e la pigrizia si applicano solo ai limiti a destra: i quantificatori avidi ottengono le sottostringhe fino ai limiti più a destra, e quelle pigre corrisponderanno fino alla prima occorrenza dei subpattern da seguire.

Vedi le esempi:

> library(stringr) 
> str_extract('xxx aaaab yyy', "a[^ab]*b") 
[1] "ab" 
> str_extract('xxx aaa xxx aaa zzz', "xxx.*?zzz") 
[1] "xxx aaa xxx aaa zzz" 
> str_extract('xxx aaa xxx aaa zzz', "xxx(?:(?!xxx|zzz).)*zzz") 
[1] "xxx aaa zzz" 

Il primo e il terzo scenario riportare la finestra più breve, il secondo è un'illustrazione del problema attuale ma con un ingresso multicarattere.

Scenario 1. I confini sono singoli caratteri

In caso a e b sono singoli caratteri, la finestra più breve è determinato usando una classe di caratteri negata. a[^ab]*b facilmente afferrare la sottostringa da a fino al prossimo b senza a se b s in mezzo.

Scenario 2. I confini non sono singoli caratteri

È possibile utilizzare un tempered greedy token in questi casi che possono essere ulteriormente srotolato. Il modello xxx(?:(?!xxx|zzz).)*zzz corrisponde xxx, allora qualsiasi 0+ caratteri diversi da un char di riga che non è il char di partenza di una sequenza char xxx o zzz (il (?!xxx|zzz) è un lookahead negativo che fallisce la partita se la stringa immediatamente alle partite giuste il modello lookahead), quindi un zzz.

Questi corrispondenza scenari può essere facilmente utilizzato con base R regmatches (usando un sapore PCRE regex che supporta lookaheads):

> x <- 'xxx aaa xxx aaa zzz xxx bbb xxx ccc zzz' 
> unlist(regmatches(x, gregexpr("xxx(?:(?!xxx|zzz).)*zzz", x, perl = TRUE))) 
[1] "xxx aaa zzz" "xxx ccc zzz" 

Una nota: quando si utilizza una regex PCRE nella base di R, o ICU regex in str_extract/str_match, il . non corrisponde ai caratteri di interruzione di riga, per abilitare tale comportamento, è necessario aggiungere (?s) all'avvio del modello (un modificatore DOTALL in linea).

Problemi correlati