I have strings like follows :
Hi this is %1$s, product %2$s
Hi this is %2$s, product %2$s
I want to replace %1$s
Your pattern is wrong, you have at the start [a-z]
, so you aren't detecting anything.
Also, prefers utf16 count with NSStuff (because with NSString, it's UTF16)
let myString = "Hi this is %1$s, product %2$s Hi this is %2$s, product %2$s"
let range = NSRange(location: 0, length: myString.utf16.count)
var regex = try! NSRegularExpression(pattern: "%(\\d+)\\$s", options: [])
var newStr = regex.stringByReplacingMatches(in: myString, options: [], range: range, withTemplate: "{$1}")
print(newStr)
Output:
$>Hi this is {1}, product {2} Hi this is {2}, product {2}
Some explanation on %(\d+)\$s
(and then redo a \
for Swift strings).
%
: Detect "%"
\d+
: Detect number (including 12 which weren't your case before)
(\d+)
: Detect number, but in a capture group
\$
: Detect "$" (need an escape because it's a special char in regex)
s
: Detect "s"
So there are two groups: The whole (corresponding to the whole regex match), and the numbers. The first one would be $0, and the second one $1, that's why I used {$1}
in the template.
NB: I used https://regex101.com to check the pattern.
With increment, you can't do it with the template. You have to enumerate all the matches, do the operation and replace.
var myString = "Hi this is %1$s, product %2$s Hi this is %2$s, product %2$s"
let range = NSRange(location: 0, length: myString.utf16.count)
var regex = try! NSRegularExpression(pattern: "%(\\d+)\\$s", options: [])
let matches = regex.matches(in: myString, options: [] , range: range)
matches.reversed().forEach({ aMatch in
let fullNSRange = aMatch.range
guard let fullRange = Range(fullNSRange, in: myString) else { return }
let subNSRange = aMatch.range(at: 1)
guard let subRange = Range(subNSRange, in: myString) else { return }
let subString = myString[subRange]
guard let subInt = Int(subString) else { return }
let replacement = "{" + String(subInt + 1) + "}"
myString.replaceSubrange(fullRange, with: replacement)
})