我尝试编写一些代码,我在字符串中迭代正则表达式匹配并对匹配运行操作,将其替换为操作的结果。我遇到了问题,我的replacementString()
内部覆盖了第二次和后续匹配的提供范围,如果先前的替换字符串不是,则不匹配源字符串中的位置与原始匹配子串的长度完全相同。
我构建了一个简单的例子来演示这个问题。
var str : NSMutableString = "Hello, hello, jello!"
class MyConverter : NSRegularExpression {
override func replacementString(for result: NSTextCheckingResult,
in string: String,
offset: Int,
template templ: String) -> String {
let theRange = result.range(at: 0)
let theSubStr = NSString(string: string).substring(with: theRange)
return super.replacementString(for: result,
in: string,
offset: offset,
template: self.magic(theSubStr))
}
func magic(_ text: String) -> String {
print("Converting \(text) to lloy")
return "lloy"
}
}
var regex = try? MyConverter(pattern: "llo", options: [])
let matches = regex?.replaceMatches(in: str,
options: [],
range: NSRange(location: 0, length: str.length),
withTemplate: "$0")
print(str)
我期望的输出是:
Converting llo to lloy
Converting llo to lloy
Converting llo to lloy
Helloy, helloy, jelloy!
但是,我得到的输出是:
Converting llo to lloy
Converting ell to lloy
Converting jel to lloy
Helloy, helloy, jelloy!
最终替换放在正确的位置,但由于我试图对匹配的文本运行操作,我需要在我的magic()
方法中显示正确的子字符串。
我可以尝试跟踪匹配中的差异以及生成的替换字符串,并通过+/-来修改每个范围,或者强制整个事物只需迭代matches()
直到没有&#39任何左翼,但我想知道是否有更优雅的方式来完成这项工作。
答案 0 :(得分:1)
将offset
添加到theRange
的开头。来自method reference:
offset
:要添加到字符串中结果位置的偏移量。
override func replacementString(for result: NSTextCheckingResult,
in string: String,
offset: Int,
template templ: String) -> String {
var theRange = result.range(at: 0)
theRange.location += offset
let theSubStr = NSString(string: string).substring(with: theRange)
return super.replacementString(for: result,
in: string,
offset: offset,
template: self.magic(theSubStr))
}