0

I'm very confused using Swift's regular expression for replacing strings. I want to replace <blubb>Test</blubb> which does not work as expected:

let html  = "Test\r\nTest\r\nTest\r\nTest\r\nTest\r\nTest\r\nTest-<blubb>Test</blubb>-Test"
do {
    let regex = try NSRegularExpression(pattern: "\\<blubb\\>[\\s\\S]*\\<\\/blubb\\>", options: NSRegularExpression.Options.caseInsensitive)
    let range = NSMakeRange(0, html.count)
    let modString = regex.stringByReplacingMatches(in: html, options: [], range: range, withTemplate: "REPLACED")
    print( modString)
} catch {}

Result (not replacing string):

Test
Test
Test
Test
Test
Test
Test-<blubb>Test</blubb>-Test

But:

  • If I remove all \r it works
  • If I remove first Test\r\n it works too

Result of removing first Test\r\n:

Test
Test
Test
Test
Test
Test-REPLACED-Test

So am I missing something or is this a bug in the regex-engine used by Swift?

coyer
  • 4,122
  • 3
  • 28
  • 35
  • The reason – as explained in the duplicate Q&A – is that `html.count` is the “wrong count” for an NSRange. Use `html.utf16.count` or (better) the dedicated constructor `let range = NSRange(html.startIndex..., in: html)` – Martin R Sep 26 '19 at 13:59
  • 1
    In your case `\r\n` counts as a single Swift Character, but as two `NSString` characters, so that `html.count` is “too small.” – Martin R Sep 26 '19 at 14:02

0 Answers0