2013-03-22 15 views
8

Sto cercando di dividere una stringa di un modulo generico, in cui le parentesi quadre indicano le "sezioni" della stringa. Es:split string with regex

x <- "[a] + [bc] + 1" 

e restituire un vettore di carattere che assomiglia:

"[a]" " + " "[bc]" " + 1" 

EDIT: finito per usare questo:

x <- "[a] + [bc] + 1" 
x <- gsub("\\[",",[",x) 
x <- gsub("\\]","],",x) 
strsplit(x,",") 

risposta

6

Ho visto il codice di TylerRinker e il sospetto che potrebbe essere più chiaro di così, ma questo può servire come modo per imparare un diverso insieme di funzioni. (Mi è piaciuto il suo meglio prima ho notato che si divide su spazi.) Ho provato ad adattarlo per funzionare con strsplit ma quella funzione rimuove sempre i separatori. Forse questo potrebbe essere adattato per fare un newstrsplit che si divide ai separatori ma li lascia in? Probabilmente non è necessario dividere la prima o l'ultima posizione e distinguere tra separatori di apertura e chiusura.

scan(text= # use scan to separate after insertion of commas 
      gsub("\\]", "],", # put commas in after "]"'s 
      gsub(".\\[", ",[", x)) , # add commas before "[" unless at first position 
     what="", sep=",") # tell scan this character argument and separators are "," 
#Read 4 items 
#[1] "[a]" " +" "[bc]" " + 1" 
+0

Mi piace questo approccio in quanto non dipende dallo spazio bianco per la divisione. Mantenere lo spazio bianco nell'output non era importante per questa attività, quindi l'ho modificato per funzionare con 'strplit': –

+0

Grazie per il commento positivo, ma considero @ juba una risposta migliore. Lo userò per costruire una semplice funzione di analisi che accetta una coppia di argomenti per segnalare i delimitatori di inizio e fine che verranno preservati. –

5

Questo è un approccio pigro:

FUN <- function(x) { 
    all <- unlist(strsplit(x, "\\s+")) 
    last <- paste(c(" ", tail(all, 2)), collapse="") 
    c(head(all, -2), last) 
} 

x <- "[a] + [bc] + 1"  
FUN(x) 

## > FUN(x) 
## [1] "[a]" "+" "[bc]" " +1" 
+0

si dice 'pigro' perché si sta utilizzando gli spazi piuttosto che utilizzare le staffe separare? –

+0

Sì (nessuna reale regexing intenso) –

5

È possibile calcolare il manuall dei punti di split y e utilizzare substring:

split.pos <- gregexpr('\\[.*?]',x)[[1]] 
split.length <- attr(split.pos, "match.length") 
split.start <- sort(c(split.pos, split.pos+split.length)) 
split.end <- c(split.start[-1]-1, nchar(x)) 
substring(x,split.start,split.end) 
# [1] "[a]" " + " "[bc]" " + 1" 
+1

Eccoci. Grandi progressi verso la creazione di un "newsplit". Non che lo comprenda pienamente, ma pensavo che 'gregexpr' sarebbe stato utile. Sono rimasto sorpreso dal fatto che non hai bisogno di usare "\\]" nel pattern. –

+0

Penso che ']' non abbia bisogno di essere sfuggito perché non è interpretato come una classe di fine carattere a causa del fatto che '[' is. Hmm, non sono sicuro di essere molto chiaro :-) – juba

+0

Ho avuto lo stesso pensiero, ma suggerisce che la "particolarità" è più dipendente dal contesto di quanto mi sarei aspettato. –

5

Ed ecco una versione che si divide sulle staffe e li mantiene nel risultato, utilizzando lookahead positivo e lookbehind:

splitme <- function(x) { 
    x <- unlist(strsplit(x, "(?=\\[)", perl=TRUE)) 
    x <- unlist(strsplit(x, "(?<=\\])", perl=TRUE)) 
    for (i in which(x=="[")) { 
    x[i+1] <- paste(x[i], x[i+1], sep="") 
    } 
    x[-which(x=="[")] 
} 
splitme(x) 
#[1] "[a]" " + " "[bc]" " + 1"