Which NSRegularExpression was found using the | operator

…衆ロ難τιáo~ 提交于 2020-01-05 04:31:50

问题


I'm currently implementing NSRegularExpressions to check for patterns inside a UITextView string in my project.

The patterns check and operations are working as expected; for example: I'm trying to find the regular **bold** markdown pattern and if I find it I apply some text attributed to the range, and it works as expected.

I have though came across a problem. I don't know how to run multiple patterns at once and apply different operations for each pattern found.

In my UITextView delegate textViewDidChange or shouldChangeTextIn range: NSRange I am running the bold pattern check \\*{2}([\\w ]+)\\*{2} but then I am as well running the italic pattern check \\_{1}([\\w ]+)\\_{1}, looping again through the UITextView text.

I have implemented the following custom function, that applies the passed in regex to the string, but I have to call this function multiple times to check for each pattern, that's why I'd love to put the pattern check into one single, then "parse" each match.

fileprivate func regularExpression(regex: NSRegularExpression, type: TypeAttributes) {
    let str = inputTextView.attributedText.string
    let results = regex.matches(in: str, range: NSRange(str.startIndex..., in: str))
    _ = results.map { self.applyAttributes(range: $0.range, type: type) }
}

Thanks.

EDIT

I can "merge" both patterns with the | operand like the following:

private let combinedPattern = "\\*{2}([\\w ]+)\\*{2}|\\_{1}([\\w ]+)\\_{1}"

but my problem is to know which pattern was found the \\*{2}([\\w ]+)\\*{2} one or the \\_{1}([\\w ]+)\\_{1}


回答1:


If you use the combined pattern you have the results in different range of the match result.

If you want to access the first capture group (the bold pattern) you need to access the range at 1. When the match matches the second group you will have the first with an invalid range, so you need to check if it's valid of not this way:

results.forEach {
    var range = $0.range(at: 1)
    if range.location + range.length < str.count {
         self.applyAttributes(range: range, type: .bold)
    }
    range = $0.range(at: 2)
    if range.location + range.length < str.count {
        self.applyAttributes(range: range, type: .italic)
    }
}

After that you can extend your TypeAttributes enum to return the index range that is linked to your regular expression:

extension NSRange {
    func isValid(for string:String) -> Bool {
        return location + length < string.count
    }
}

let attributes: [TypeAttributes] = [.bold, .italic]

results.forEach { match in
    attributes.enumerated().forEach { index, attribute in
         let range = match.range(at: index+1)
         if range.isValid(for: str) {                
             self.applyAttributes(range: range, type: attribute[index]) 
         }
    }
}


来源:https://stackoverflow.com/questions/50326149/which-nsregularexpression-was-found-using-the-operator

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!