Ich möchte den Ausdruck durch mathematische Vergleiche z.
unlist(strsplit("var<3", "(?=[=<>])", perl = TRUE))
unlist(strsplit("var==5", "(?=[=<>])", perl = TRUE))
unlist(strsplit("var>2", "(?=[=<>])", perl = TRUE))
Die Ergebnisse sind:
[1] "var" "<" "3"
[1] "var" "=" "=" "5"
[1] "var" ">" "2"
Für das zweite Beispiel oben würde ich gerne bekommen [1] "var" "==" "5"
so die beiden =
sollte als einzelnes Element zurückgegeben werden. Wie muss ich meinen regulären Ausdruck ändern, um dies zu erreichen? (Ich habe bereits versucht Gruppierung und Quantifizierer für "==", aber nichts hat funktioniert - reguläre Ausdrücke sind nicht meine Freunde ...)
Antworten:
9 für die Antwort № 1Sie können eine PCRE-Regex verwenden Spiel die benötigten Teilstrings:
==|[<>]|(?:(?!==)[^<>])+
Auch zu unterstützen !=
, modifiziere es als
[!=]=|[<>]|(?:(?![=!]=)[^<>])+
Siehe die Regex-Demo.
Einzelheiten:
==
- 2=
Zeichen|
- oder[<>]
- ein<
oder>
|
- oder(?:(?!==)[^<>])+
- 1 oder mehr Zeichen außer<
und>
([^<>]
) die nicht beginnen a==
Char-Sequenz (a temperiertes gieriges Token).
HINWEIS: Dies ist leicht erweiterbar durch Hinzufügen von mehr Alternativen und Anpassung der temperierten gierigen Token.
> text <- "Text1==text2<text3><More here"
> res <- regmatches(text, gregexpr("==|[<>]|(?:(?!==)[^<>])+", text, perl=TRUE))
> res
[[1]]
[1] "Text1" "==" "text2" "<" "text3" ">"
[7] "<" "More here"
6 für die Antwort № 2
Erweitern von meiner Idee in Kommentaren, nur für die Formatierung:
tests=c("var==5","var<3","var.name>5")
regmatches(tests,regexec("([a-zA-Z0-9_.]+)(\W+)([a-zA-Z0-9_.]+)",tests))
w
ist [a-zA-Z0-9_]
und W
es ist das Gegenteil [^a-zA-Z0-9_]
Ich habe es nach dem Kommentar erweitert. in der Zeichenklasse, und wie R nicht unterstützt w in der Zeichenklasse in der Basisregex (müssen Perl verwenden = TRUE).
Also die Regex Suche für mindestens 1 von w und., Dann mindestens 1 nicht in w (um Operatoren zu entsprechen) und dann mindestens 1 von w und Punkt.
Jeder Schritt wird erfasst und dies ergibt:
[[1]]
[1] "var==5" "var" "==" "5"
[[2]]
[1] "var<3" "var" "<" "3"
[[3]]
[1] "var.name>5" "var.name" ">" "5"
du kannst hinzufügen *
zwischen den einzelnen Erfassungsgruppen, wenn Ihre Einträge Platz um den Operator haben könnten, wenn sie nicht vom Operator erfasst werden.
5 für die Antwort № 3
Mit Worten "Grenzen (\b
) und 2 Möglichkeiten für den Lookaround angeben:
unlist(strsplit("var==5", "(?=(\b[^a-zA-Z0-9])|(\b[a-zA-Z0-9]\b))", perl = TRUE))
[1] "var" "==" "5"
unlist(strsplit("var<3", "(?=(\b[^a-zA-Z0-9])|(\b[a-zA-Z0-9]\b))", perl = TRUE))
[1] "var" "<" "3"
unlist(strsplit("var>2", "(?=(\b[^a-zA-Z0-9])|(\b[a-zA-Z0-9]\b))", perl = TRUE))
[1] "var" ">" "2"
Erläuterung:
Split am Ende des "Wortes" und danach gibt es entweder ein nicht-alphanumerisches Zeichen \b[^a-zA-Z0-9]
oder es ist das Ende des "Wortes" und danach gibt es ein alphanumerisches Zeichen.
BEARBEITEN:
Tatsächlich würde der obige Code unerwartete Ergebnisse haben, wenn die Zahl am Ende 10 oder mehr ist.
Eine andere Option ist zu verwenden lookbehind
und teilen, wenn vorher ein Nicht-Alphanum-Zeichen, gefolgt von einer Wortkante, oder ein Alphanum-Zeichen, gefolgt von einer Wortkante, vorliegt:
strsplit("var<20", "(?<=(([^a-zA-Z0-9]\b)|([a-zA-Z0-9]\b)))", perl = TRUE)[[1]]
#[1] "var" "<" "20"
strsplit("var==20", "(?<=(([^a-zA-Z0-9]\b)|([a-zA-Z0-9]\b)))", perl = TRUE)[[1]]
#[1] "var" "==" "20"
strsplit("var!=5", "(?<=(([^a-zA-Z0-9]\b)|([a-zA-Z0-9]\b)))", perl = TRUE)[[1]]
#[1] "var" "!=" "5"
EDIT2:
Totally stehlen @ Tensibai Weg, um alphanum (+ Unterstrich) / non alphanum Zeichen, die oben genannten zu definieren regex
kann vereinfachen zu: "(?<=((\W\b)|(\w\b)))"