Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Match regular expression case insensitively, replace with specific case

Tags:

regex

r

I'm using regular expressions to replace some substrings. The replacement value reuses part of the match. I want to match case insensitively, but in the replacement, I want a lower case version of the thing that was matched.

library(stringi)
x <- "CatCATdog"
rx <- "(?i)(cat)(?-i)"
stri_replace_all_regex(x, rx, "{$1}")
# [1] "{Cat}{CAT}dog"

This is close to what I want, except the "cat"s should be lower case. That is, the output string should be "{cat}{cat}dog".

The following code doesn't work, but it shows my intension.

stri_replace_all_regex(x, rx, "{tolower($1)}") 

The following technique does work, but it's ugly, not very generalizable, and not very efficient. My idea was to replace the regular expression with one that matches what I want, but not the replacement values (that is, "cat" but not "{cat}"). Then search for the first match in each input string, find the location of the match, do a substring replacement, then look for the next match until there are no more. It's awful.

x <- "CatCATdog"
rx <- "(?i)((?<!\\{)cat(?!\\}))(?-i)"
repeat{
  detected <- stri_detect_regex(x, rx)
  if(!any(detected))
  {
    break
  }
  index <- stri_locate_first_regex(x[detected], rx)
  match <- tolower(stri_match_first_regex(x[detected], rx)[, 2])
  stri_sub(x[detected], index[, 1], index[, 2]) <- paste0("{", match[detected], "}")
}

I feel like there must be a better way.

How do I replace case insensitive matches with lower case values?


Thanks to inspiration from the comments, I discovered that the thing I'm looking for is "replacement text case conversion".

like image 637
Richie Cotton Avatar asked Sep 21 '26 15:09

Richie Cotton


1 Answers

If you need to perform any kind of string manipulation you may use gsubfn:

> library(gsubfn)
> rx <- "(?i)cat"
> s = "CatCATdog"
> gsubfn(rx, ~ paste0("{",tolower(x),"}"), s, backref=0)
[1] "{cat}{cat}dog"

You can use the gsubfn as you would use an anonymous callback method inside String#replace in JavaScript (you may specify the arguments for capturing groups with function(args), and also make more sophisticated manipulations inside).

like image 167
Wiktor Stribiżew Avatar answered Sep 23 '26 06:09

Wiktor Stribiżew



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!