wake-up-neo.com

Extrahieren Sie einen regulären Ausdruck

Ich versuche, eine Zahl aus einer Zeichenfolge zu extrahieren.

Und tun Sie etwas wie [0-9]+ für die Zeichenfolge "aaa12xxx" und erhalten Sie "12".

Ich dachte, es wäre so etwas wie:

> grep("[0-9]+", "aaa12xxx", value=TRUE)
[1] "aaa12xxx"

Und dann dachte ich mir ... 

> sub("[0-9]+", "\\1", "aaa12xxx")
[1] "aaaxxx"

Aber ich bekam eine Art Antwort:

> sub("[0-9]+", "ARGH!", "aaa12xxx")
[1] "aaaARGH!xxx"

Da fehlt ein kleines Detail.

87
tovare

Verwenden Sie das neue stringr-Paket, das alle vorhandenen regulären Ausdrücke in einer konsistenten Syntax umgibt und einige fehlende Elemente hinzufügt:

library(stringr)
str_locate("aaa12xxx", "[0-9]+")
#      start end
# [1,]     4   5
str_extract("aaa12xxx", "[0-9]+")
# [1] "12"
139
hadley

Es ist wahrscheinlich etwas voreilig zu sagen " ignoriert die Standardfunktionen " - die Hilfedatei für ?gsub, auch wenn in 'Siehe auch' ausdrücklich darauf verwiesen wird:

Regmatches zum Extrahieren übereinstimmender Teilzeichenfolgen basierend auf den Ergebnissen von "Regexpr", "gregexpr" und "regexec".

Das funktioniert also und ist ziemlich einfach:

txt <- "aaa12xxx"
regmatches(txt,regexpr("[0-9]+",txt))
#[1] "12"
64
thelatemail

Könnte sein

gsub("[^0-9]", "", "aaa12xxxx")
# [1] "12"
22
Marek

Sie können Perl regexs 'Lazy-Matching verwenden:

> sub(".*?([0-9]+).*", "\\1", "aaa12xx99",Perl=TRUE)
[1] "12"

Der Versuch, Nicht-Ziffern zu ersetzen, führt in diesem Fall zu einem Fehler.

Verwenden Sie zum Erfassen von Klammern im regulären Ausdruck und für die Gruppenreferenzen in der Ersetzung. Alles, was in Klammern steht, wird in Erinnerung bleiben. Dann wird mit\2 der erste Eintrag aufgerufen. Der erste Backslash entgeht der Interpretation des Backslash in R, so dass er an den Parser für reguläre Ausdrücke übergeben wird.

gsub('([[:alpha:]]+)([0-9]+)([[:alpha:]]+)', '\\2', "aaa12xxx")
4
Ragy Isaac

Mit strapply im gsubfn-Paket. strapply ist wie zutreffend, wenn die Argumente object, modifier und function sind, mit der Ausnahme, dass das Objekt ein Vektor von Strings ist (und nicht ein Array) und der Modifier ein regulärer Ausdruck (und nicht ein Rand) ist:

library(gsubfn)
x <- c("xy13", "ab 12 cd 34 xy")
strapply(x, "\\d+", as.numeric)
# list(13, c(12, 34))

Dies bedeutet, dass eine oder mehrere Ziffern (\ d +) in jeder Komponente von x übereinstimmen, die jedes Match als.numeric durchläuft. Sie gibt eine Liste zurück, deren Komponenten Vektoren von Übereinstimmungen der jeweiligen Komponenten von x sind. Wenn Sie die at-Ausgabe betrachten, sehen Sie, dass die erste Komponente von x eine Übereinstimmung hat, die 13 ist, und die zweite Komponente von x zwei Übereinstimmungen aufweist, die 12 und 34 sind. Siehe http://gsubfn.googlecode.com für weitere Informationen .

2
G. Grothendieck

Eine Möglichkeit wäre dies: 

test <- regexpr("[0-9]+","aaa12456xxx")

Beachten Sie, dass mit regexpr die Start- und Endindizes der Zeichenfolge angezeigt werden:

    > test
[1] 4
attr(,"match.length")
[1] 5

Sie können diese Informationen also mit der substr-Funktion verwenden

substr("aaa12456xxx",test,test+attr(test,"match.length")-1)

Ich bin sicher, dass es einen eleganteren Weg gibt, dies zu tun, aber dies war der schnellste Weg, den ich finden konnte. Alternativ können Sie sub/gsub verwenden, um herauszufinden, was Sie nicht verlassen möchten. 

2
Robert

Eine andere Lösung:

temp = regexpr('\\d', "aaa12xxx");
substr("aaa12xxx", temp[1], temp[1]+attr(temp,"match.length")[1])
1
pari

Ein wichtiger Unterschied zwischen diesen Ansätzen ist das Verhalten bei Nichtübereinstimmung. Beispielsweise gibt die Methode "regmatches" möglicherweise keine Zeichenfolge mit der gleichen Länge wie die Eingabe zurück, wenn nicht in allen Positionen eine Übereinstimmung besteht

> txt <- c("aaa12xxx","xyz")

> regmatches(txt,regexpr("[0-9]+",txt)) # could cause problems

[1] "12"

> gsub("[^0-9]", "", txt)

[1] "12" ""  

> str_extract(txt, "[0-9]+")

[1] "12" NA  
0
andyyy