Regex grepl for specific and repeating pattern

Viewed 324

To match strings of the format "lkas32kj_123_3.21" I use (in R)

grepl("^[[:alnum:]]+_[[:digit:]]+_[[:digit:]]+\\.{0,1}[[:digit:]]+$", "lkas32kj_123_3.21")

How can I extend this to cases with | repeating/compound strings of any length such as (length three) "lkas32kj_123_3.21|l3kj_12_0.21|123e_4_32.1".

Is there a way to make a nested (recursive ?) pattern ?

1 Answers

You may use

"^[[:alnum:]]+(?:_\\d+){2}(?:\\.\\d+)?(?:\\|[[:alnum:]]+(?:_\\d+){2}(?:\\.\\d+)?)*$"

See the regex demo

In R, use

x <- c("lkas32kj_123_3.21", "lkas32kj_123_3.21|l3kj_12_0.21|123e_4_32.1", "+++NO+++")
rx <- "[[:alnum:]]+(?:_\\d+){2}(?:\\.\\d+)?"
grepl(paste0("^", rx, "(?:\\|", rx ,")*$"), x)

See the R demo online.

The pattern is like this: ^{single_item_regex}(?:\|{single_item_regex})*$. It matches:

  • ^ - start of string
  • {single_item_regex} - the pattern you have for the single item (note I replaced [[:digit:]] with \d to make it shorter, but if you need to stick to the POSIX character class, you may)
  • (?: - start of a non-capturing group:
    • \| - a pipe
    • {single_item_regex} - the single item pattern
  • )* - end of group, repeat 0 or more times
  • $ - end of string.

In the single item pattern, I suggest replacing \.{0,1}\d+ with (?:\.\d+)? as the intention here is to match an optional . and 1+ digits at the end.

Related