* vs .* in R with regexp

Viewed 69

Why does R (at least with tidyverse/stringr) recognize the following regexp: *\.(png|jpg|jpeg)? (in R due to character escaping one actually needs to write the string "*\\.(png|jpg|jpeg)")

I think the correct regexp should be .*\.(png|jpg|jpeg) (writing in R ".*\\.(png|jpg|jpeg)"))

When i introduce the first expression on e.g. regex101.com, it says that is is an illegal regexp. But R seems to parse it without issues.

Why?

Is the expression *\.(png|jpg|jpeg) a valid regular expression? If so, why does regex101 complain? If not, why does R accept it?

1 Answers

If you use the base R regex functions with the default TRE regex library, the * at the start of the pattern will get ignored. It is in line with how POSIX based regex engines behave, see this sed demo (this tool uses POSIX BRE in the demo).

TRE regex engine being a POSIX based regex engine ignores the * at the start of the regex:

> gsub("*\\.png$", "", "abc.png")
[1] "abc"

However, other NFA regex engines treat it as an error:

> library(stringr)
> str_replace("abc.png", "*\\.png$", "")
Error in stri_replace_first_regex(string, pattern, fix_replacement(replacement),  : 
  Syntax error in regexp pattern. (U_REGEX_RULE_SYNTAX, context=`*\.png$`)
> gsub("*\\.png$", "", "abc.png", perl=TRUE)
Error in gsub("*\\.png$", "", "abc.png", perl = TRUE) : 
  invalid regular expression '*\.png$'
In addition: Warning message:
In gsub("*\\.png$", "", "abc.png", perl = TRUE) :
  PCRE pattern compilation error
        'quantifier does not follow a repeatable item'
        at '*\.png$'

stringr regex functions use the ICU regex library and base R regex functions with perl=TRUE use the PCRE regex library (not perl!)

Related