Ваш шаблон неправильный, у вас в начале [a-z]
, поэтому вы ничего не обнаруживаете.
Кроме того, предпочитает считать utf16 с NSStuff (потому что с NSString это 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)
Вывод:
$>Hi this is {1}, product {2} Hi this is {2}, product {2}
Некоторое объяснение %(\d+)\$s
(а затем повторить \
для строк Swift).
%
: Определить "%"
\d+
: обнаружение номера (включая 12, которое раньше не было в вашем случае)
(\d+)
: обнаружение номера, но в группе захвата
\$
: обнаружение «$» (нужен побег, потому что это специальный char в регулярном выражении)
s
: определение "s"
Таким образом, есть две группы: целое (соответствующее всему совпадению регулярного выражения) и числа. Первый из них будет $ 0, а второй $ 1, поэтому я использовал {$1}
в шаблоне.
Примечание: я использовал https://regex101.com для проверки шаблона.
С увеличением вы не можете сделать это с шаблоном. Вы должны перечислить все совпадения, выполнить операцию и заменить.
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)
})