【问题标题】:How to replace a string with its uppercase with NSRegularExpression in Swift?如何在 Swift 中用 NSRegularExpression 替换大写的字符串?
【发布时间】:2017-03-10 23:27:26
【问题描述】:

我试图通过这个 sn-p 代码 (Swift 3.0) 将 hello_world 更改为 helloWorld

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")

结果是newLine = "helloLworld"

我使用"\\L$2" 作为模板,因为我看到了这个答案:https://stackoverflow.com/a/20742304/5282792\L$2 是替换模板中第二组大写的模式。但它在NSRegularExpression 中不起作用。

那么我可以用NSRegularExpression 中的替换模板模式替换一个大写的字符串吗?

【问题讨论】:

  • SublimeText 使用支持 \L 运算符的 Boost 正则表达式。 Swift 使用 ICU,不支持大小写运算符。
  • @WiktorStribiżew 所以NSRegularExpression 在替换模板中只支持$num
  • 反斜杠也是 ICU 正则表达式替换模式中的特殊字符,请参阅 ICU User Guide: Replacement Text
  • 您是否打算为此使用正则表达式?我可以使用String 上的方法为您提供一些代码,这些代码可以很好地满足您的需求。

标签: regex swift


【解决方案1】:

处理您的案例的一种方法是继承 NSRegularExpression 并覆盖 replacementString(for:in:offset:template:) 方法。

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

【讨论】:

    【解决方案2】:

    这并不能回答有关正则表达式的问题,但对于不一定需要使用正则表达式来执行此任务(而是使用本机 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
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-06-17
      • 2021-03-01
      • 2016-07-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-21
      • 2016-06-05
      相关资源
      最近更新 更多