R Language
Reguliere expressies (regex)
Zoeken…
Invoering
Reguliere expressies (ook "regex" of "regexp" genoemd) definiëren patronen die kunnen worden vergeleken met een string . Typ ?regex
voor de officiële R-documentatie en raadpleeg de Regex-documenten voor meer informatie. De belangrijkste 'gotcha' die niet zal worden geleerd in de SO-regex / onderwerpen is dat de meeste R-regex-functies het gebruik van gepaarde backslashes nodig hebben om te ontsnappen in een pattern
.
Opmerkingen
Karakter klassen
-
"[AB]"
kan A of B zijn -
"[[:alpha:]]"
kan elke letter zijn -
"[[:lower:]]"
staat voor elke kleine letter. Merk op dat"[az]"
dichtbij is maar niet overeenkomt, bijvoorbeeldú
. -
"[[:upper:]]"
staat voor elke hoofdletter. Merk op dat"[AZ]"
dichtbij is maar niet overeenkomt, bijv.Ú
. -
"[[:digit:]]"
staat voor elk cijfer: 0, 1, 2, ... of 9 en is gelijk aan"[0-9]"
.
quantifiers
+
, *
en ?
zoals gebruikelijk in regex toepassen. - +
komt minimaal één keer overeen, *
komt 0 of meer keer overeen, en ?
komt overeen met 0 of 1 keer.
Begin en einde van lijnindicatoren
U kunt de positie van de regex in de tekenreeks opgeven:
-
"^..."
forceert de reguliere expressie aan het begin van de string -
"...$"
forceert de reguliere expressie aan het einde van de string
Verschillen met andere talen
Houd er rekening mee dat reguliere expressies in R er vaak iets zo anders uitzien dan reguliere expressies die in andere talen worden gebruikt.
R vereist dubbele backslash-escapes (omdat
"\"
al in het algemeen in R-strings impliceert), dus om bijvoorbeeld witruimte in de meeste reguliere expressie-engines vast te leggen, moet je gewoon\s
, versus\\s
in R typen .UTF-8-tekens in R moeten worden ontsnapt met een hoofdletter U, bijvoorbeeld
[\U{1F600}]
en[\U1F600]
match 😀, terwijl in bijvoorbeeld Ruby dit zou worden gekoppeld aan een kleine u.
Aanvullende bronnen
De volgende site reg101 is een goede plek om online regex te controleren voordat u het R-script gebruikt.
De R Programming wikibook heeft een pagina gewijd aan tekstverwerking met veel voorbeelden met reguliere expressies.
Witruimte elimineren
string <- ' some text on line one;
and then some text on line two '
Witruimte bijsnijden
Witruimte "trimmen" verwijst meestal naar het verwijderen van zowel voorloop- als volgwitruimte uit een string. Dit kan worden gedaan met een combinatie van de vorige voorbeelden. gsub
wordt gebruikt om de vervanging te forceren voor zowel de voorloopwedstrijden als de gsub
.
Voorafgaand aan R 3.2.0
gsub(pattern = "(^ +| +$)",
replacement = "",
x = string)
[1] "some text on line one; \nand then some text on line two"
R 3.2.0 en hoger
trimws(x = string)
[1] "some text on line one; \nand then some text on line two"
Voorloopruimte verwijderen
Voorafgaand aan R 3.2.0
sub(pattern = "^ +",
replacement = "",
x = string)
[1] "some text on line one; \nand then some text on line two "
R 3.2.0 en hoger
trimws(x = string,
which = "left")
[1] "some text on line one; \nand then some text on line two "
Verwijder de laatste witruimte
Voorafgaand aan R 3.2.0
sub(pattern = " +$",
replacement = "",
x = string)
[1] " some text on line one; \nand then some text on line two"
R 3.2.0 en hoger
trimws(x = string,
which = "right")
[1] " some text on line one; \nand then some text on line two"
Alle witruimte verwijderen
gsub(pattern = "\\s",
replacement = "",
x = string)
[1] "sometextonlineone;andthensometextonlinetwo"
Merk op dat hiermee ook witruimtetekens zoals tabs ( \t
), nieuwe regels ( \r
en \n
) en spaties worden verwijderd.
Valideer een datum in een "YYYYMMDD" -indeling
Het is gebruikelijk om bestanden een naam te geven als prefix in de volgende notatie: YYYYMMDD
, bijvoorbeeld: 20170101_results.csv
. Een datum in een dergelijke tekenreeksindeling kan worden geverifieerd met de volgende reguliere expressie:
\\d{4}(0[1-9]|1[012])(0[1-9]|[12][0-9]|3[01])
De bovenstaande uitdrukking beschouwt datums uit het jaar: 0000-9999
, maanden tussen: 01-12
en dagen 01-31
.
Bijvoorbeeld:
> grepl("\\d{4}(0[1-9]|1[012])(0[1-9]|[12][0-9]|3[01])", "20170101")
[1] TRUE
> grepl("\\d{4}(0[1-9]|1[012])(0[1-9]|[12][0-9]|3[01])", "20171206")
[1] TRUE
> grepl("\\d{4}(0[1-9]|1[012])(0[1-9]|[12][0-9]|3[01])", "29991231")
[1] TRUE
Opmerking : het valideert de syntaxis van de datum, maar we kunnen een verkeerde datum hebben met een geldige syntaxis, bijvoorbeeld: 20170229
(2017 is geen schrikkeljaar).
> grepl("\\d{4}(0[1-9]|1[012])(0[1-9]|[12][0-9]|3[01])", "20170229")
[1] TRUE
Als u een datum wilt valideren, kan dit via deze door de gebruiker gedefinieerde functie:
is.Date <- function(x) {return(!is.na(as.Date(as.character(x), format = '%Y%m%d')))}
Vervolgens
> is.Date(c("20170229", "20170101", 20170101))
[1] FALSE TRUE TRUE
Valideer postafkortingen in de VS.
De volgende regex
omvat 50 staten en ook Commonwealth / Territory (zie www.50states.com ):
regex <- "(A[LKSZR])|(C[AOT])|(D[EC])|(F[ML])|(G[AU])|(HI)|(I[DLNA])|(K[SY])|(LA)|(M[EHDAINSOT])|(N[EVHJMYCD])|(MP)|(O[HKR])|(P[WAR])|(RI)|(S[CD])|(T[NX])|(UT)|(V[TIA])|(W[AVIY])"
Bijvoorbeeld:
> test <- c("AL", "AZ", "AR", "AJ", "AS", "DC", "FM", "GU","PW", "FL", "AJ", "AP")
> grepl(us.states.pattern, test)
[1] TRUE TRUE TRUE FALSE TRUE TRUE TRUE TRUE TRUE TRUE FALSE FALSE
>
Opmerking :
Als u alleen de 50 staten wilt verifiëren, raden we u aan om de R-gegevensset: state.abb
van state
, bijvoorbeeld:
> data(state)
> test %in% state.abb
[1] TRUE TRUE TRUE FALSE FALSE FALSE FALSE FALSE FALSE TRUE FALSE FALSE
We krijgen alleen TRUE
voor afkortingen van 50 staten: AL, AZ, AR, FL
.
Valideer Amerikaanse telefoonnummers
De volgende reguliere expressie:
us.phones.regex <- "^\\s*(\\+\\s*1(-?|\\s+))*[0-9]{3}\\s*-?\\s*[0-9]{3}\\s*-?\\s*[0-9]{4}$"
Valideert een telefoonnummer in de vorm van: +1-xxx-xxx-xxxx
, inclusief optionele voorloop- / volgspaties aan het begin / einde van elke groep nummers, maar niet in het midden, bijvoorbeeld: +1-xxx-xxx-xx xx
is niet geldig. De -
begrenzer kan worden vervangen door spaties: xxx xxx xxx
of zonder begrenzer: xxxxxxxxxx
. Het voorvoegsel +1
is optioneel.
Laten we het controleren:
us.phones.regex <- "^\\s*(\\+\\s*1(-?|\\s+))*[0-9]{3}\\s*-?\\s*[0-9]{3}\\s*-?\\s*[0-9]{4}$"
phones.OK <- c("305-123-4567", "305 123 4567", "+1-786-123-4567",
"+1 786 123 4567", "7861234567", "786 - 123 4567", "+ 1 786 - 123 4567")
phones.NOK <- c("124-456-78901", "124-456-789", "124-456-78 90",
"124-45 6-7890", "12 4-456-7890")
Geldige gevallen:
> grepl(us.phones.regex, phones.OK)
[1] TRUE TRUE TRUE TRUE TRUE TRUE TRUE
>
Ongeldige gevallen:
> grepl(us.phones.regex, phones.NOK)
[1] FALSE FALSE FALSE FALSE FALSE
>
Opmerking :
-
\\s
Komt overeen met elke spatie, elk tabblad of elk nieuweteken
Ontsnappende personages in R-regexpatronen
Omdat zowel R als regex het escape-teken "\"
, is het vaak nodig om backslashes te koppelen om correcte patronen te maken voor grep
, sub
, gsub
of een andere functie die een patroonargument accepteert. Als je een vector met drie itemtekens bouwt waarin een item een linefeed heeft, een ander een tab-teken en een geen van beide, en hij wil de linefeed of het tabblad in 4 spaties veranderen, dan is een enkele backslash nodig voor de constructie, maar getrapte backslashes voor matching:
x <- c( "a\nb", "c\td", "e f")
x # how it's stored
# [1] "a\nb" "c\td" "e f"
cat(x) # how it will be seen with cat
#a
#b c d e f
gsub(patt="\\n|\\t", repl=" ", x)
#[1] "a b" "c d" "e f"
Merk op dat het patroonargument (dat optioneel is als het eerst verschijnt en slechts gedeeltelijke spelling behoeft) het enige argument is dat deze verdubbeling of koppeling vereist. Het vervangingsargument vereist niet dat de tekens moeten worden verdubbeld. Als u alle linefeeds en gebeurtenissen met 4 spaties wilt vervangen door tabbladen, zou dit zijn:
gsub("\\n| ", "\t", x)
#[1] "a\tb" "c\td" "e\tf"
Verschillen tussen Perl en POSIX-regex
Er zijn twee ooit zo enigszins verschillende engines voor reguliere expressies geïmplementeerd in R. De standaardinstelling wordt POSIX-consistent genoemd; alle regex-functies in R zijn ook uitgerust met een optie om het laatste type in te schakelen: perl = TRUE
.
Look-ahead / look-achter
perl = TRUE
maakt vooruit kijken en achterom kijken mogelijk in reguliere expressies.
-
"(?<=A)B"
overeen met de verschijning van de letterB
als deze wordt voorafgegaan doorA
, dwz"ABACADABRA"
zou worden vergeleken, maar"abacadabra"
en"aBacadabra"
niet.