Regex pattern match and replace in Swift

前端 未结 1 615
梦如初夏
梦如初夏 2021-01-28 11:47

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

相关标签:
1条回答
  • 2021-01-28 12:06

    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)
    })
    
    0 讨论(0)
提交回复
热议问题