Nsregularexpression replacingOccurrences with multiple templates

Asked

Viewed 36 times

1

I’m having difficulties to replace different templates in a text, my Regex returns more than one need to replace according to the variable value strReplaced

Follows code:

    import Foundation
let texto = "Bem-[sexo:vindo,vinda] à aventura de viver a vida sendo você [sexo:mesmo,mesma], a partir de um espaço de liberdade, de escolhas e de possibilidades!"

protocol FilterTagProtocol {
    var pattern: String { get }
}
struct FilterTagManager {
    enum FiltersTexts: String, CaseIterable, FilterTagProtocol {
        case gender = "\\[sexo:([^]]*)\\]"
        case name = "\\[nome\\]"
        var pattern: String {
            return self.rawValue
        }
    }

    func replaceGender(text: String) -> String {
        let split = text.split(separator: ",")
        if split.count > 1 {
            let male = String(split[0])
            let female = String(split[1])
            if split.count != 2 || male.count == 0 || female.count == 0 {
                return ""
            } else {
                return male
            }
        }
        return text
    }

    private func replaceName(text: String) -> String {
        return "Mike"
    }

    func applyFilter(text: String, filter: FiltersTexts) -> String {
        do {
            let regEx = try NSRegularExpression(pattern: filter.pattern, options: [.anchorsMatchLines])
            let matches = regEx.matches(in: text, options: [], range: NSRange(location: 0, length: text.utf16.count))
            if matches.count > 0 {
                let rangeAt = filter == .name ? 0 : 1
                let substring = (text as NSString).substring(with: (matches.first?.range(at: rangeAt))!)
                return substring
            }
        } catch {
            print("ERROR applyFilter: ", error.localizedDescription)
            return text
        }
        return text
    }

    func replace(text: String, filter: FiltersTexts) -> String {
        let textFiltered = applyFilter(text: text, filter: filter)
        switch filter {
        case .gender:
            return replaceGender(text: textFiltered)
        case .name:
            return replaceName(text: textFiltered)
        }
    }

    func replaceText(from text: String, type: FiltersTexts) -> (newString: String, range: NSRange)? {
        do {
            let regEx = try NSRegularExpression(pattern: type.pattern, options: [])
            let matches = regEx.matches(in: text, options: [], range: NSRange(location: 0, length: text.utf16.count))
            for match in matches as [NSTextCheckingResult] {
                let textNS = (text as NSString)
                let strReplaced = replace(text: text, filter: type)
                let innerContentBlock = textNS.substring(with: match.range)
                let newString = text.replacingOccurrences(of: innerContentBlock, with: strReplaced)
                return (newString: newString, range: match.range)
            }
        } catch {
            print(error.localizedDescription)
            return nil
        }
        return nil
    }

    func replaceTexts(from text: String, type: FiltersTexts) -> String? {
        let templates = matches(for: type.pattern, in: text)
        var newText = text
        for template in templates {
            let strReplaced = replace(text: template, filter: type)
            if newText.contains(template) {
                newText = newText.replacingOccurrences(of: template, with: strReplaced)
            }
        }
        return newText
    }

    func matches(for regex: String, in text: String) -> [String] {
        do {
            let regex = try NSRegularExpression(pattern: regex)
            let results = regex.matches(in: text,
                                        range: NSRange(text.startIndex..., in: text))
            let finalResult = results.map {
                String(text[Range($0.range, in: text)!])
            }
            return finalResult
        } catch let error {
            print("invalid regex: \(error.localizedDescription)")
            return []
        }
    }

    func normalizeTexts(contentBlock: String) -> String {
        var brokenText = contentBlock
        for filter in FiltersTexts.allCases {
            if let filterBlock = replaceTexts(from: brokenText, type: filter) {
                brokenText = filterBlock
            }
        }
        return brokenText
    }
}



let filter = FilterTagManager()
let newText = filter.normalizeTexts(contentBlock: texto)
print(newText)

the same is also in GIST: https://gist.github.com/micheltlutz/47f7ddce882be31be7fafa33c594f819

Does anyone have any better suggestions?

  • Corrected as follows 
func replaceTexts(from text: String, type: FiltersTexts) -> String? {
 let templates = matches(for: type.pattern, in: text)
 var newText = text
 for template in templates {
 let strReplaced = replace(text: template, filter: type)
 if newText.contains(template) {
 newText = newText.replacingOccurrences(of: template, with: strReplaced)
 }
 }
 return newText
 }
 If someone has a better shape

No answers

Browser other questions tagged

You are not signed in. Login or sign up in order to post.