2013-09-04 3 views
12

Gegeben ein regulärer Ausdruck, der capture groups (Klammern) und einen String enthält, wie kann ich alle die Teilstrings erhalten, die die Capture-Gruppen entsprechen, dh die Teilstrings, die normalerweise von "\ 1" referenziert werden. \ 2 "?Entnehmen Sie Capture-Gruppenübereinstimmungen aus regulären Ausdrücken? (oder: wo ist gregexec?)

Beispiel: Ein regex Capturing Ziffern betrachten von "xy" vorangestellt:

s <- "xy1234wz98xy567" 

r <- "xy(\\d+)" 

Wunschergebnis:

[1] "1234" "567" 

Erster Versuch: gregexpr:

regmatches(s,gregexpr(r,s)) 
#[[1]] 
#[1] "xy1234" "xy567" 

nicht, was ich will weil es die Teilstrings zurückgibt, die dem gesamten Muster entsprechen.

Zweiter Versuch: regexec:

regmatches(s,regexec("xy(\\d+)",s)) 
#[[1]] 
#[1] "xy1234" "1234" 

nicht, was ich will, weil es gibt nur das erste Auftreten einer Anpassung für das gesamte Muster und der Capture-Gruppe.

Wenn es eine gregexec Funktion gab, die regexec als gregexpr erweitert erweitert regexpr, würde mein Problem gelöst werden.

Die Frage ist also: wie alle Teilstrings (oder Indizes, die wie in den obigen Beispielen an regmatches übergeben werden können) abgerufen werden, passend zu Capture-Gruppen in einem beliebigen regulären Ausdruck?

Hinweis: das oben angegebene Muster für r ist nur ein dummes Beispiel, es muss willkürlich bleiben.

Antwort

11

Nicht sicher dies in der Basis zu tun, aber hier ist ein Paket für Ihre Bedürfnisse:

library(stringr) 

str_match_all(s, r) 
#[[1]] 
#  [,1]  [,2] 
#[1,] "xy1234" "1234" 
#[2,] "xy567" "567" 

Viele stringr Funktionen auch Parallelen in der Basis R, so dass Sie auch diese stringr ohne Verwendung erreichen können.

Zum Beispiel, hier ist eine vereinfachte Version, wie die oben genannten Arbeiten, Base R mit:

sapply(regmatches(s,gregexpr(r,s))[[1]], function(m) regmatches(m,regexec(r,m))) 
+1

Dies ist genau das, was ich brauche. Ich werde seine Quelle überprüfen. Ich glaube, es gibt (oder sollte) eine Lösung in der Basis R, da dies eine grundlegende Aufgabe ist. –

+1

Es verwendet nur 'lapply' und' regexec' (wenn auch geschickt) ... Geben Sie einfach 'str_match_all' und' str_match' ein, um das zu sehen ... – Arun

8

strapplyc im gsubfn package das tun:

> library(gsubfn) 
> 
> strapplyc(s, r) 
[[1]] 
[1] "1234" "567" 

Versuchen ?strapplyc für weitere Informationen und Beispiele.

ähnliche Funktionen

1) Eine Verallgemeinerung ist strapplycstrapply im gleichen Paket. Es benötigt eine Funktion, die die erfassten Teile jeder Übereinstimmung eingibt und die Ausgabe der Funktion zurückgibt. Wenn die Funktion c ist, wird sie auf strapplyc reduziert.Angenommen, wir zurückgehen als numerische wollen:

> strapply(s, r, as.numeric) 
[[1]] 
[1] 1234 567 

2)gsubfn ist eine weitere Funktion eines im selben Paket. Es ist wie gsub, außer dass die Ersetzungszeichenfolge eine Ersetzungsfunktion (oder eine Ersetzungsliste oder ein Ersetzungs-Proto-Objekt) sein kann. Die Ersatzfunktion gibt die erfassten Teile ein und gibt den Ersatz aus. Die Ersetzung ersetzt die Übereinstimmung in der Eingabezeichenfolge. Wenn eine Formel verwendet wird, wie in diesem Beispiel, wird die rechte Seite der Formel als Funktionskörper betrachtet. In diesem Beispiel ersetzen wir die Übereinstimmung durch XY{#}, wobei # die doppelte übereinstimmende Eingabezahl ist.

> gsubfn(r, ~ paste0("XY{", 2 * as.numeric(x), "}"), s) 
[1] "XY{2468}wz98XY{1134}" 

UPDATE: Added strapply und gsubfn Beispiele.

+0

Das ist großartig. Eine Frage: nennt 'strapplyc'' regexec' in einer Schleife, wie 'stringr :: str_match_all'? –

+0

'strapplyc' verwendet den zugrunde liegenden Code, der in tcl (eine String-Verarbeitungssprache) geschrieben ist, um sehr große Strings und Geschwindigkeit zu verarbeiten (es sei denn, das Argument' engine = 'gibt eine andere Engine an). Siehe '? Strapplyc' für Details. –

+0

Vielen Dank für diese Antwort. Ich akzeptierte Eddi's, weil er richtig ist und zuerst antwortete. –

12

Für eine Basis-R-Lösung, was ist nur mit gsub() zu Ende Verarbeitung der Strings extrahiert von gregexpr() und regmatches()?

s <- "xy1234wz98xy567" 
r <- "xy(\\d+)" 

gsub(r, "\\1", regmatches(s,gregexpr(r,s))[[1]]) 
# [1] "1234" "567" 
+0

Netter Trick, aber es kann fehlschlagen, wenn zum Beispiel die Erfassungsgruppe in einem Lookaround ist ('perl = TRUE'). –

+0

@ Ferdinand.kraft - Würden Sie ein Beispiel geben? Ich denke, dass Blicke nicht erfasst werden, also bin ich nicht in der Lage zu sehen, was du meinst. –

+0

Betrachten Sie dies: 'r <-" xy (? = (\\ d +)) "; gsub (r, "\\ 1", Regmatches (s, gregexpr (r, s, perl = WAHR)) [[1]], perl = TRUE); gsub (r, "\\ 1", s, perl = WAHR) '. Beachten Sie, dass 'gsub' (alleine) die Ziffern in' \ 1' abrufen kann. –

Verwandte Themen