How to replace a string with its uppercase with NS

2020-03-29 23:37发布

I was trying to change hello_world to helloWorld by this snippet of code (Swift 3.0):

import Foundation

let oldLine = "hello_world"
let fullRange = NSRange(location: 0, length: oldLine.characters.count)
let newLine = NSMutableString(string: oldLine)

let regex = try! NSRegularExpression(pattern: "(_)(\\w)", options: [])
regex.replaceMatches(in: newLine, options: [], range: fullRange, 
    withTemplate: "\\L$2")

The result was newLine = "helloLworld"

I used "\\L$2" as template because I saw this answer: https://stackoverflow.com/a/20742304/5282792 saying \L$2 is the pattern for the second group's uppercase in replacement template. But it didn't work in NSRegularExpression.

So can I replace a string with its uppercase with a replacement template pattern in NSRegularExpression.

标签: regex swift
2条回答
乱世女痞
2楼-- · 2020-03-30 00:15

One way to work with your case is subclassing NSRegularExpression and override replacementString(for:in:offset:template:) method.

class ToUpperRegex: NSRegularExpression {
    override func replacementString(for result: NSTextCheckingResult, in string: String, offset: Int, template templ: String) -> String {
        guard result.numberOfRanges > 2 else {
            return ""
        }
        let matchingString = (string as NSString).substring(with: result.rangeAt(2)) as String
        return matchingString.uppercased()
    }
}

let oldLine = "hello_world"
let fullRange = NSRange(0..<oldLine.utf16.count) //<-
let tuRegex = try! ToUpperRegex(pattern: "(_)(\\w)")
let newLine = tuRegex.stringByReplacingMatches(in: oldLine, range: fullRange, withTemplate: "")
print(newLine) //->helloWorld
查看更多
Viruses.
3楼-- · 2020-03-30 00:25

This doesn't answer the question pertaining regex, but might be of interest for readers not necessarily needing to use regex to perform this task (rather, using native Swift)

extension String {
    func camelCased(givenSeparators separators: [Character]) -> String {
        let charChunks = characters.split { separators.contains($0) }
        guard let firstChunk = charChunks.first else { return self }
        return String(firstChunk).lowercased() + charChunks.dropFirst()
            .map { String($0).onlyFirstCharacterUppercased }.joined()
    }

    // helper (uppercase first char, lowercase rest)
    var onlyFirstCharacterUppercased: String {
        let chars = characters
        guard let firstChar = chars.first else { return self }
        return String(firstChar).uppercased() + String(chars.dropFirst()).lowercased()
    }
}

/* Example usage */
let oldLine1 = "hello_world"
let oldLine2 = "fOo_baR BAX BaZ_fOX"

print(oldLine1.camelCased(givenSeparators: ["_"]))      // helloWorld
print(oldLine2.camelCased(givenSeparators: ["_", " "])) // fooBarBazBazFox
查看更多
登录 后发表回答