6

I am trying to replace instances in a string which begin with abc in a text I'm working with in R. The output text is highlighted in HTML over a couple of passes, so I need the replacement to ignore text inside HTML carets.

The following seems to work in Python but I'm not getting any hits on my regex in R. All help appreciated.

test <- 'abcdef abc<span abc>defabc abcdef</span> abc defabc'
gsub('\\babc\\(?![^<]*>\\)', 'xxx', test)

Expected output:

xxxdef xxx<span abc>defabc xxxdef</span> xxx defabc

Instead it is ignoring all instances of abc.

0m3r
  • 12,286
  • 15
  • 35
  • 71
Rich Ard
  • 151
  • 11

1 Answers1

7

You need to remove unnecessary escapes and use perl=TRUE:

test <- 'abcdef abc<span abc>defabc abcdef</span> abc defabc'
gsub('\\babc(?![^<]*>)', 'xxx', test, perl=TRUE)
## => [1] "xxxdef xxx<span abc>defabc xxxdef</span> xxx defabc"

See the online R demo

When you escape (, it matches a literal ( symbol, so, in your pattern, \\(?![^<]*>\\) matches a ( 1 or 0 times, then !, then 0+ chars other than <, then > and a literal ). In my regex, (?![^<]*>) is a negative lookahead that fails the match if an abc is followed with any 0+ chars other than < and then a >.

Without perl=TRUE, R gsub uses the TRE regex flavor that does not support lookarounds (even lookaheads). Thus, you have to tell gsub via perl=TRUE that you want the PCRE engine to be used.

See the online PCRE regex demo.

Wiktor Stribiżew
  • 607,720
  • 39
  • 448
  • 563