Rich Ard
Rich Ard

Reputation: 191

Negative lookahead in R not behaving as expected

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.

Upvotes: 6

Views: 1741

Answers (1)

Wiktor Stribiżew
Wiktor Stribiżew

Reputation: 626896

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.

Upvotes: 7

Related Questions