1

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 by {0}, and %2$s by {1} and so on..

I have tried to make:

let range = NSRange(location: 0, length: myString.count)
var regex = try! NSRegularExpression(pattern: "%[1-9]\\$s", options: [])
var newStr = regex.stringByReplacingMatches(in: myString, options: [], range: range, withTemplate: "XXXX")

Anyone can help me, please!

7
  • You can try this. let newString = aString.replacingOccurrences(of: "%2$s ", with: "1") Commented Apr 3, 2020 at 11:16
  • it doesn't work Commented Apr 3, 2020 at 11:51
  • Quick question: What is the meaning of [a-z] at the start of your pattern? Did you try your regex with an online regex tool? Commented Apr 3, 2020 at 12:07
  • Ah sorry I have removed it later but forgot to update it here Commented Apr 3, 2020 at 12:12
  • The problem now is it repaces all occurrence with same number let us say {1} intended behavior is {1}, then {2} Commented Apr 3, 2020 at 12:15

1 Answer 1

1

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)
})
Sign up to request clarification or add additional context in comments.

2 Comments

You just saved my day! Thanks a lot
Hi @Larme Can I ask you a question what about if I want to subtract each no by 1 ex: myString = "Hi this is {0}, product {1}, ..."

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.