2012-01-12 13 views
5

Ho un vettore pieno di corde del seguente formato: <year1><year2><id1><id2>R Regular Expression lookbehind

le prime registrazioni del vettore si presenta in questo modo:

199719982001 
199719982002 
199719982003 
199719982003 

Per la prima voce che abbiamo: year1 = 1997, anno2 = 1998, id1 = 2, id2 = 001.

Voglio scrivere un'espressione regolare che estrae year1, id1 e le cifre di id2 che non sono zero. Così, per la prima voce la regex dovrebbe uscita: 199721.

Ho provato a fare questo con il pacchetto stringr, e ha creato la seguente espressione regolare:

"^\\d{4}|\\d{1}(?<=\\d{3}$)" 

di tirare fuori year1 e ID1, tuttavia quando si utilizza il lookbehind ottengo un errore di "espressione regolare non valida". Questo è un po 'sconcertante per me, R non può gestire lookaheads e lookbehinds?

+3

guardare la pagina di aiuto 'regex'. Lookbehind è supportato per 'perl = TRUE'. Quindi 'regexp ("^\\ d {4} | \\ d {1} (? <= \\ d {3} $) ", s)' non genera un errore, ma non seleziona quello che vuoi. – mpiktas

+0

Grazie per il suggerimento! Sapevo che la regex non avrebbe catturato tutto, stavo solo sperimentando un po 'e sono stato calpestato quando ricevevo un messaggio di "espressione regolare non valida". –

+0

Con 'strapply' in gsubfn questa espressione regolare funziona e non richiede lookahead o lookbehind:' L <- c ("199719982001", "199719982002", "199719982003", "199719982003"); biblioteca (gsubfn); strapply (L, "^ (....) .... (.) 0 * (. *)", c, simplify = TRUE) ' –

risposta

8

Poiché questo è un formato fisso, perché non utilizzare substr? year1 viene estratto utilizzando substr(s,1,4), id1 viene estratto utilizzando substr(s,9,9) e id2 come as.numeric(substr(s,10,13)). Nell'ultimo caso ho usato as.numeric per eliminare gli zeri.

+1

Grazie a mpiktas, avremmo dovuto pensarci. Sono comunque ancora curioso del perché il lookbehind non funziona ... –

+0

Vedere la mia altra risposta :) – mpiktas

9

È necessario utilizzare gregexpr dal pacchetto base. Questo funziona:

> s <- "199719982001" 
> gregexpr("^\\d{4}|\\d{1}(?<=\\d{3}$)",s,perl=TRUE) 
[[1]] 
[1] 1 12 
attr(,"match.length") 
[1] 4 1 
attr(,"useBytes") 
[1] TRUE 

Nota l'impostazione perl=TRUE. Per ulteriori dettagli, consulta ?regex.

Tuttavia, a giudicare dall'output, l'espressione regolare non cattura lo id1.

1

È possibile utilizzare sub.

sub("^(.{4}).{4}(.{1}).*([1-9]{1,3})$","\\1\\2\\3",s) 
+0

Grazie per il suggerimento! –

Problemi correlati