2016-02-11 13 views
14

Ich versuche strsplit() in R zu verwenden, um eine Zeichenfolge in Teile basierend auf Kommas zu brechen, aber ich möchte nichts in Klammern aufteilen. Ich denke, die Antwort ist eine Regex, aber ich habe Mühe, den Code richtig zu machen.Mit strsplit() in R, ignorieren alles in Klammern

So zum Beispiel:

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

Wenn was würde Ich mag ist:

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

Sie versuchen, die geschweiften Klammern '(...)' als nicht splitable Block Scope zu verwenden und Ihre Absicht in die Splitting Regexp zu setzen. Dies ist keine einfache Aufgabe. – huckfinn

Antwort

14

Wir PCRE Regex FAIL jeder , verwenden können, die folgt, dass ein ( vor dem ) und geteilt durch , gefolgt von 0 oder mehr Leerzeichen (\\s*)

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

Ich würde eine andere Regex mit (*SKIP)(*F) vorschlagen alle (...) Substrings zu ignorieren und nur die Kommas außerhalb von klammerten Teil entsprechen:

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

Siehe IDEONE demo

Sie mehr über How do (*SKIP) or (*F) work on regex? hier lesen kann. Die Regex passt:

  • \( - eine öffnende Klammer
  • [^()]* - null oder mehr Zeichen andere als ( und )
  • \) - ein Schließbügel
  • (*SKIP)(*F) - die Verben, die den aktuellen Regex Index voran in die Position nach der schließenden Klammer
  • | - oder ...
  • \\h*,\\h* - ein Komma, das mit null oder mehr horizontalen Leerzeichen umgeben ist.
+0

Hast du das Konto von * stribizhev * geklaut? o_O –

+0

@BhargavRao: Es ist mein Konto, ich habe nur den Namen geändert. Sie können es einmal im Monat auf SO :) –

+1

Das ist großartig. Vielen Dank! –

1

Ein anderer Ansatz:

auf @ Probe Zeichenfolge des Wiktor Hinzufügen

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

Nun ist die Magie:

> 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?" 

Wie funktioniert , |(?>\\(.*?\\).*?\\K(, |$)) Spiel?

  • | fängt eine der beiden Gruppen auf beiden Seiten, sowohl
    • auf der linken Seite, die Zeichenfolge ,
    • und rechts, (?>\\(.*?\\).*?\\K(, |$)):
      • (?> ...) Sätze up an atomic group, die erlaubt kein Zurückverfolgen, um neu zu bewerten, was es zusammenbringt.
      • In diesem Fall sieht es für eine offene Klammer (\\(),
      • dann ein beliebiges Zeichen (.) von 0 bis unendlich mal wiederholt (*), aber so wenig wie möglich (?), dh . lazily ausgewertet .
      • Die vorherige . Wiederholung dann durch die erste schließende Klammer (\\)) begrenzt ist,
      • von einem anderen Satz von jedem Zeichen folgte wiederholt 0 bis so wenig wie möglich (.*?)
      • mit a \\K am Ende, das wirft weg das Spiel bis jetzt und setzt den Ausgangspunkt eines neuen Spiels.
      • Die vorherige .*? wird durch eine Erfassungsgruppe ((...)) mit einem | beschränkt, die entweder
        • eine tatsächliche Textfolge auswählt, ,,
        • oder verschiebt \\K zum Ende der Zeile, $, wenn sind keine Kommas mehr.

* Puh. *

Wenn meine Erklärung verwirrend ist, sehen Sie die Dokumentation über verknüpft, und schauen Sie sich regex101.com, wo Sie in der obigen regex setzen können (Einzel escaped- \ - anstelle von R-Stil Doppel-Escape-\\) und eine Test-String, um zu sehen, was es übereinstimmt und eine Erklärung bekommen, was es macht. Sie müssen den Modifikator g (global) im Feld neben der Regex-Box festlegen, um alle Übereinstimmungen anzuzeigen und nicht nur die erste.

Glücklich strsplit ing!

+0

Sehr hilfreich. Vielen Dank! –

Verwandte Themen