2016-05-30 15 views
1

Ich habe eine Zeichenfolge, in der ich versuche, das erste übereinstimmende Muster mit einem entsprechenden Ersatz zu ersetzen. ZB in meinem Beispiel unten: Wenn bb zuerst gefunden wird, ersetzen Sie es durch foo und ersetzen Sie nichts anderes, aber wenn cc zuerst gefunden wird, ersetzen Sie es durch bar und ersetzen Sie nichts anderes.stringis stri_replace_first_regex Ersatz nicht als Regex

Dies verhält sich fast wie gewünscht, außer das replacement Argument wird nicht als Regex interpretiert, sondern als eine ganze Zeichenfolge. (Aber das pattern Argument wird als Regex, wie erforderlich, gesehen).

stri_replace_first_regex(
    c(" bb cc bb cc "," cc bb cc bb ", " aa bb cc "), 
    pattern = " bb | cc ", 
    replacement = " foo | bar ") 

ouputs: " foo | bar cc bb cc " " foo | bar bb cc bb " " aa foo | bar cc "

während ich möchte es Ausgabe " foo cc bb cc " " bar bb cc bb" " aa foo cc "

Irgendeine Idee, wie man das lösen?

Danke.

Weitere Kontext:

Meine Eingänge können im Grunde fast alle Formatierungen, sie sind Post-Adressen von Kunden eingegeben, in denen ich brauche die Art der Straße standardisiert durch etwas zu ersetzen (zum Beispiel drehen street in st, road in rd und avenue in av). Irgendwelche dieser Wörter können wieder erscheinen (zB 20 bis road of sesame street), daher betrachte ich nur die erste Erscheinung als gültig, und das nachfolgende Erscheinen eines Wortes aus der pattern Liste darf nicht ersetzt werden.

+1

kann ein Ersatzmuster keinen RegexMuster enthält: pattern und replacement vektorisiert, also, wenn Sie ihnen einen Vektor von Strings übergeben, wird jedes Muster mit dem jeweiligen Ersatz ersetzt werden. Ist es ein wörtliches 'bb' und' cc' oder nur Musterplatzhalter? Ich denke, sie sind nur Platzhalter hier. –

+0

Ich bin mir nicht sicher, ob ich Ihre Frage verstehe: Ich habe Postanschriften, und ich möchte das Wort, das den Straßentyp angibt, durch etwas Normiertes ersetzen: "1 Straße von welcher Straße" bis "1 von welcher Straße", "1 Straße von welcher Straße "zu" 1. von welcher Straße "und" 1 Straße von welcher Straße "zu" 1. von welcher Straße auch immer ". Also wären meine zwei Regexes 'pattern =" street | road "' und 'replacement =" st | rd "'. Ich hoffe, das beantwortet deine Frage. –

+2

'v <- Vektorisieren (sub); v (c ('bb', 'cc'), c ('foo', 'bar'), c ("bb cc bb cc", "cc bb cc bb")) ' – rawr

Antwort

3

können Sie verwenden qdap Bibliothek mgsub für diesen Ersatz:

> input <- c("1 road of whatever road", "1 street of whatever street") 
> pattern = c("^(.*?)\\bstreet\\b","^(.*?)\\broad\\b") 
> replacement = c("\\1st","\\1rd") 
> mgsub(pattern, replacement, input, fixed=FALSE, perl=TRUE) 
[1] "1 rd of whatever road" "1 st of whatever street" 

Die Muster ^ (Beginn der Zeichenfolge) umfassen, (.*?) eine Erfassungsgruppe alle Zeichen, sondern ein Newline so wenig wie möglich bis zu den passenden erstes Auftreten der ganzen Wörter (aufgrund der Wortgrenzen \b) street und road.

Die Ersetzungsmuster haben Rückverweise (\\1) auf den Text, der mit den einfangenden Gruppen und den zu ersetzenden Wörtern erfasst wurde.

+0

Installieren Sie das Paket jetzt, um es zu versuchen Dies.Wenn ich jedoch Ihrer Ausgabe vertraue, ersetzt dies alles und nicht nur das erste Wort: "1. von was auch immer RD" "1. von was auch immer ST" "während ich brauche" 1. von was auch immer ROAD "" 1. von was auch immer STREET "' (Großbuchstabe ist nur für Betonung) –

+0

@fmalaussena gibt es wahrscheinlich eine 'Msub'-Funktion in diesem Paket, benutze das stattdessen – rawr

+0

Ich aktualisierte die Frage um zu zeigen, wie man das erste ganze Wort nur ersetzt. HINWEIS: Falls Ihre Strings Zeilenumbrüche enthalten können, fügen Sie '(? S)' am Anfang der Muster hinzu: 'pattern = c (" (? S)^(. *?) \\ bstreet \\ b "," (? s)^(. *?) \\ broad \\ b ")' –

0

?stringi::stri_replace_first_regex lesen;

stringi::stri_replace_first_regex(
    c(" bb cc bb cc "," cc bb cc bb "), 
    pattern = c("bb", "cc"), 
    replacement = c("foo", "bar")) 
# [1] " foo cc bb cc " " bar bb cc bb " 
+0

Versuchen 'stri_replace_first_regex ( c ("cc bb cc", "cc bb cc bb "), Muster = C (" BB", "cc"), Ersatz = c ("foo", "bar")) 'und Sie werden sehen, dass es sich nicht wie gewünscht verhält, da die Ausgabe ist" cc foo cc "" bar bb cc bb "' und nicht '" foo bb cc "" bar bb cc bb "' –

+0

Gut ja, Es iteriert über die Muster, denn wenn es versucht, beide Zeichenfolgen auf einmal zu vergleichen, können sie sich überlappen. Sie könnten den Anfang der Zeile '^' in Ihre Regex integrieren, wenn Sie wissen, wo es ist, oder das wird ein Schmerz sein. Mehr Kontext kann jedoch mehr Optionen beleuchten. – alistaire

+0

BTW: in Betracht ziehen, das 'vectorize_all' Argument von' stringi :: stri_replace_all_regex 'zu verwenden – gagolews