Frage Regex-Gruppenerfassung in R mit mehreren Erfassungsgruppen


In R, ist es möglich, Gruppenaufnahmen aus einem regulären Ausdruck zu extrahieren? Soweit ich das beurteilen kann, keine grep, grepl, regexpr, gregexpr, sub, oder gsub die Gruppenaufnahmen zurückgeben.

Ich muss Schlüssel-Wert-Paare aus Strings extrahieren, die so codiert sind:

\((.*?) :: (0\.[0-9]+)\)

Ich kann immer nur mehrere Full-Match-Greps machen oder eine externe (Nicht-R-) Verarbeitung durchführen, aber ich hatte gehofft, dass ich alles innerhalb von R machen kann. Gibt es eine Funktion oder ein Paket, das eine solche Funktion bietet?


75
2018-06-04 18:25


Ursprung


Antworten:


str_match(), von dem stringr Paket, wird dies tun. Es gibt eine Zeichenmatrix mit einer Spalte für jede Gruppe in der Übereinstimmung (und eine für die gesamte Übereinstimmung) zurück:

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

96
2018-04-06 03:13



gsub macht das, aus Ihrem Beispiel:

gsub("\\((.*?) :: (0\\.[0-9]+)\\)","\\1 \\2", "(sometext :: 0.1231313213)")
[1] "sometext 0.1231313213"

Sie müssen doppelt die \ s in den Anführungszeichen entkommen dann arbeiten sie für die Regex.

Hoffe das hilft.


39
2018-06-04 22:44



Versuchen regmatches() und regexec():

regmatches("(sometext :: 0.1231313213)",regexec("\\((.*?) :: (0\\.[0-9]+)\\)","(sometext :: 0.1231313213)"))
[[1]]
[1] "(sometext :: 0.1231313213)" "sometext"                   "0.1231313213"

21
2018-05-15 11:32



gsub () kann dies tun und nur die Capture-Gruppe zurückgeben:

Damit dies funktioniert, müssen Sie explizit Elemente außerhalb Ihrer Erfassungsgruppe auswählen, wie in der Hilfe zu gsub () erwähnt.

(...) Elemente von Zeichenvektoren 'x', die nicht substituiert sind, werden unverändert zurückgegeben.

Wenn also der auszuwählende Text in der Mitte eines Strings liegt, sollten Sie durch Hinzufügen von. * Vor und nach der Capture-Gruppe nur den String zurückgeben.

gsub(".*\\((.*?) :: (0\\.[0-9]+)\\).*","\\1 \\2", "(sometext :: 0.1231313213)") [1] "sometext 0.1231313213"


16
2018-04-26 21:43



Ich mag Perl-kompatible reguläre Ausdrücke. Wahrscheinlich tut jemand anderes auch ...

Hier ist eine Funktion, die Perl-kompatible reguläre Ausdrücke erfüllt und die Funktionalität von Funktionen in anderen Sprachen, die ich gewohnt bin, erfüllt:

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
}

3
2018-01-29 16:53



So habe ich dieses Problem gelöst. Ich habe zwei separate Regexes verwendet, um die ersten und zweiten Capture-Gruppen zu erreichen und zwei zu führen gregexpr Aufrufe, dann ziehen Sie die übereinstimmenden Teilstrings heraus:

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

2
2018-06-05 16:06



Wie in der stringr Paket kann dies mit beiden erreicht werden str_match() oder str_extract().

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(strings, phone)
# [1] "219 733 8965" "329-293-8753" NA             "239 923 8115" "579-499-7527" NA            
# [7] "543.355.3679"

Gruppen mit einer Ausgabematrix anzeigen (wir interessieren uns für die Spalten 2+):

str_match(strings, phone)
#      [,1]           [,2]  [,3]  [,4]  
# [1,] "219 733 8965" "219" "733" "8965"
# [2,] "329-293-8753" "329" "293" "8753"
# [3,] NA             NA    NA    NA    
# [4,] "239 923 8115" "239" "923" "8115"
# [5,] "579-499-7527" "579" "499" "7527"
# [6,] NA             NA    NA    NA    
# [7,] "543.355.3679" "543" "355" "3679"

1
2017-12-23 15:37



Lösung mit strcapture von 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

1
2017-08-24 01:22