2016-02-11 14 views
14

Sto provando a utilizzare strsplit() in R per dividere una stringa in pezzi in base alle virgole, ma non voglio suddividere nulla tra parentesi. Penso che la risposta sia una regex ma sto lottando per ottenere il codice giusto.Uso di strsplit() in R, ignorando qualsiasi cosa tra parentesi

Così, per esempio:

x <- "This is it, isn't it (well, yes)" 
> strsplit(x, ", ") 
[[1]] 
[1] "This is it"  "isn't it (well" "yes)" 

Quando ciò che vorrei è:

[1] "This is it"  "isn't it (well, yes)" 
+0

Si tenta di utilizzare le parentesi '(...)' come un ambito di blocco non divisibile e si deve inserire l'espressione nella suddivisione regolare. Questo non è un compito semplice. – huckfinn

risposta

14

possiamo usare PCRE regex per FAIL qualsiasi , che segue che un ( prima della ) e dividere per , seguito da 0 o più spazio (\\s*)

strsplit(x, '\\([^)]+,(*SKIP)(*FAIL)|,\\s*', perl=TRUE)[[1]] 
#[1] "This is it"   "isn't it (well, yes)" 
6

Vorrei suggerire un'altra espressione regolare con (*SKIP)(*F) di ignorare tutte le (...) sottostringhe e solo abbinare le virgole al di fuori di sottostringhe tra parentesi:

x <- "This is it, isn't it (well, yes), and (well, this, that, and this, too)" 
strsplit(x, "\\([^()]*\\)(*SKIP)(*F)|\\h*,\\h*", perl=T) 

Vedi IDEONE demo

Si può leggere di più su How do (*SKIP) or (*F) work on regex? qui. La regex:

  • \( - una parentesi di apertura
  • [^()]* - zero o più caratteri diversi ( e )
  • \) - una parentesi di chiusura
  • (*SKIP)(*F) - verbi che promuovono l'indice regex corrente alla posizione dopo la parentesi di chiusura
  • | - o ...
  • \\h*,\\h* - una virgola circondata da zero o più spazi bianchi orizzontali.
+0

Hai dirottato l'account di * stribizhev *? o_O –

+0

@BhargavRao: è il mio account, ho appena cambiato il nome. Puoi farlo una volta al mese su SO :) –

+1

Questo è fantastico. Grazie! –

1

Un approccio diverso:

Aggiunta a @ stringa di esempio di Wiktor,

x <- "This is it, isn't it (well, yes), and (well, this, that, and this, too). Let's look, does it work?" 

Ora la magia:

> strsplit(x, ", |(?>\\(.*?\\).*?\\K(, |$))", perl = TRUE) 
[[1]] 
[1] "This is it"          
[2] "isn't it (well, yes)"        
[3] "and (well, this, that, and this, too). Let's look" 
[4] "does it work?" 

Così come fa , |(?>\\(.*?\\).*?\\K(, |$)) partita?

  • | cattura uno dei gruppi su entrambi i lati, sia
    • sulla sinistra, la stringa ,
    • e, sulla destra, (?>\\(.*?\\).*?\\K(, |$)):
      • (?> ...) set up an atomic group, che non consente il backtracking per rivalutare ciò che corrisponde.
      • In questo caso, esso cerca una parentesi aperta (\\(),
      • quindi qualsiasi carattere (.) ripetuto da 0 a volte infinito (*), ma il meno possibile (?), cioè . viene valutata pigramente .
      • Il precedente . ripetizione è quindi limitata dalla prima parentesi chiusa (\\)),
      • seguita da un'altra serie di carattere ripetuto 0 a meno possibile (.*?)
      • con a \\K alla fine, che getta via la partita finora e imposta il punto di partenza di una nuova partita.
      • Il precedente .*? è limitato da un gruppo di acquisizione ((...)) con un | che o
        • seleziona una stringa di testo effettivo, ,,
        • o sposta \\K alla fine della linea, $, se ci non ci sono più virgole

* Accidenti. *

Se la mia spiegazione è confuso, vedere i documenti legati sopra, e controllare regex101.com, dove si può mettere nel regex sopra (singolo fuggito- \ -instead di R-style double fuggito- \\) e una stringa di test per vedere cosa corrisponde e ottenere una spiegazione di ciò che sta facendo. Dovrai impostare il modificatore g (globale) nella casella accanto alla casella regex per mostrare tutte le corrispondenze e non solo la prima.

Happy strsplit ing!

+0

Molto utile. Grazie! –

Problemi correlati