【问题标题】:NSRegularExpression.replacementString doesn't track changes in string lengthNSRegularExpression.replacementString 不跟踪字符串长度的变化
【发布时间】:2018-09-28 01:20:30
【问题描述】:

我正在尝试编写一些代码,在其中迭代字符串中的正则表达式匹配并对匹配运行操作,将其替换为操作结果。不过,我遇到了问题,在我的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() 方法中。

我可以尝试跟踪匹配项和生成的替换字符串的差异,并通过 +/- ... 修改每个范围,但我想知道是否有更优雅的方式来完成这项工作。

【问题讨论】:

    标签: swift4 nsregularexpression swift4.1


    【解决方案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))
    }
    

    【讨论】:

    • 啊!所以我错过了一些明显的东西。谢谢!
    猜你喜欢
    • 1970-01-01
    • 2014-06-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多