Ist es in R möglich, die Gruppenerfassung aus einer Übereinstimmung mit regulären Ausdrücken zu extrahieren? Soweit ich das beurteilen kann, gibt es keine von grep
, grepl
, regexpr
, gregexpr
, sub
oder gsub
gibt die Gruppenerfassungen zurück.
Ich muss Schlüssel-Wert-Paare aus Zeichenfolgen extrahieren, die folgendermaßen codiert sind:
\((.*?) :: (0\.[0-9]+)\)
Ich kann immer nur mehrere vollständige Match-Greps ausführen oder einige externe (nicht-R-) Verarbeitungsschritte ausführen, aber ich hatte gehofft, dass ich alles innerhalb von R ausführen kann. Gibt es eine Funktion oder ein Paket, das eine solche Funktion bietet, um dies zu tun?
str_match()
aus dem stringr
-Paket erledigt dies. Es wird eine Zeichenmatrix mit einer Spalte für jede Gruppe in der Übereinstimmung (und eine für die gesamte Übereinstimmung) zurückgegeben:
> s = c("(sometext :: 0.1231313213)", "(moretext :: 0.111222)")
> str_match(s, "\\((.*?) :: (0\\.[0-9]+)\\)")
[,1] [,2] [,3]
[1,] "(sometext :: 0.1231313213)" "sometext" "0.1231313213"
[2,] "(moretext :: 0.111222)" "moretext" "0.111222"
gsub macht das, aus deinem Beispiel:
gsub("\\((.*?) :: (0\\.[0-9]+)\\)","\\1 \\2", "(sometext :: 0.1231313213)")
[1] "sometext 0.1231313213"
sie müssen die\s in den Anführungszeichen doppelt maskieren, dann funktionieren sie für den regulären Ausdruck.
Hoffe das hilft.
Versuchen Sie regmatches()
und regexec()
:
regmatches("(sometext :: 0.1231313213)",regexec("\\((.*?) :: (0\\.[0-9]+)\\)","(sometext :: 0.1231313213)"))
[[1]]
[1] "(sometext :: 0.1231313213)" "sometext" "0.1231313213"
gsub () kann dies und gibt nur die Erfassungsgruppe zurück:
Damit dies funktioniert, müssen Sie jedoch explizit Elemente außerhalb Ihrer Erfassungsgruppe auswählen, wie in der gsub () - Hilfe angegeben.
(...) Elemente von Zeichenvektoren 'x', die nicht ersetzt werden, werden unverändert zurückgegeben.
Wenn sich Ihr auszuwählender Text also in der Mitte einer Zeichenfolge befindet, sollten Sie beim Hinzufügen von. * Vor und nach der Erfassungsgruppe nur diese Zeichenfolge zurückgeben können.
gsub(".*\\((.*?) :: (0\\.[0-9]+)\\).*","\\1 \\2", "(sometext :: 0.1231313213)") [1] "sometext 0.1231313213"
Ich mag Perl-kompatible reguläre Ausdrücke. Wahrscheinlich tut es auch jemand anderes ...
Hier ist eine Funktion, die Perl-kompatible reguläre Ausdrücke ausführt und die Funktionalität von Funktionen in anderen Sprachen, die ich gewöhnt bin, vergleicht:
regexpr_Perl <- function(expr, str) {
match <- regexpr(expr, str, Perl=T)
matches <- character(0)
if (attr(match, 'match.length') >= 0) {
capture_start <- attr(match, 'capture.start')
capture_length <- attr(match, 'capture.length')
total_matches <- 1 + length(capture_start)
matches <- character(total_matches)
matches[1] <- substr(str, match, match + attr(match, 'match.length') - 1)
if (length(capture_start) > 1) {
for (i in 1:length(capture_start)) {
matches[i + 1] <- substr(str, capture_start[[i]], capture_start[[i]] + capture_length[[i]] - 1)
}
}
}
matches
}
So habe ich dieses Problem umgangen. Ich habe zwei separate reguläre Ausdrücke verwendet, um die erste und die zweite Erfassungsgruppe abzugleichen, zwei gregexpr
-Aufrufe ausgeführt und dann die übereinstimmenden Teilzeichenfolgen abgerufen:
regex.string <- "(?<=\\().*?(?= :: )"
regex.number <- "(?<= :: )\\d\\.\\d+"
match.string <- gregexpr(regex.string, str, Perl=T)[[1]]
match.number <- gregexpr(regex.number, str, Perl=T)[[1]]
strings <- mapply(function (start, len) substr(str, start, start+len-1),
match.string,
attr(match.string, "match.length"))
numbers <- mapply(function (start, len) as.numeric(substr(str, start, start+len-1)),
match.number,
attr(match.number, "match.length"))
Wie im Paket stringr
vorgeschlagen, kann dies entweder mit str_match()
oder str_extract()
erreicht werden.
Aus dem Handbuch übernommen:
library(stringr)
strings <- c(" 219 733 8965", "329-293-8753 ", "banana",
"239 923 8115 and 842 566 4692",
"Work: 579-499-7527", "$1000",
"Home: 543.355.3679")
phone <- "([2-9][0-9]{2})[- .]([0-9]{3})[- .]([0-9]{4})"
Extrahieren und Kombinieren unserer Gruppen:
str_extract_all(strings, phone, simplify=T)
# [,1] [,2]
# [1,] "219 733 8965" ""
# [2,] "329-293-8753" ""
# [3,] "" ""
# [4,] "239 923 8115" "842 566 4692"
# [5,] "579-499-7527" ""
# [6,] "" ""
# [7,] "543.355.3679" ""
Anzeigen von Gruppen mit einer Ausgabematrix (wir interessieren uns für Spalten 2+):
str_match_all(strings, phone)
# [[1]]
# [,1] [,2] [,3] [,4]
# [1,] "219 733 8965" "219" "733" "8965"
#
# [[2]]
# [,1] [,2] [,3] [,4]
# [1,] "329-293-8753" "329" "293" "8753"
#
# [[3]]
# [,1] [,2] [,3] [,4]
#
# [[4]]
# [,1] [,2] [,3] [,4]
# [1,] "239 923 8115" "239" "923" "8115"
# [2,] "842 566 4692" "842" "566" "4692"
#
# [[5]]
# [,1] [,2] [,3] [,4]
# [1,] "579-499-7527" "579" "499" "7527"
#
# [[6]]
# [,1] [,2] [,3] [,4]
#
# [[7]]
# [,1] [,2] [,3] [,4]
# [1,] "543.355.3679" "543" "355" "3679"
Lösung mit strcapture
aus dem utils
:
x <- c("key1 :: 0.01",
"key2 :: 0.02")
strcapture(pattern = "(.*) :: (0\\.[0-9]+)",
x = x,
proto = list(key = character(), value = double()))
#> key value
#> 1 key1 0.01
#> 2 key2 0.02