【问题标题】:Convert UPPERCASE to Title Case将大写字母转换为大写字母
【发布时间】:2015-09-22 07:02:09
【问题描述】:

我想快速将大写字符串(UPPERCASE)转换为标题大小写字符串(Title Case)。我不擅长正则表达式,但发现this 用我尝试使用的正则表达式回答。

搜索表达式为:

"([A-Z])([A-Z]+)\b"

模板表达式为:

"$1\L$2"

为了快速使用它,我已经转义了反斜杠,如下所示:

var uppercase = "UPPER CASE STRING"
var titlecase = uppercase.stringByReplacingOccurrencesOfString("([A-Z])([A-Z]+)\\b", withString: "$1\\L$2", options: NSStringCompareOptions.RegularExpressionSearch, range: Range<String.Index>(start: uppercase.startIndex, end: uppercase.endIndex))

上面的代码给出以下结果:

"ULPPER CLASE SLTRING"

从中可以看出搜索表达式成功找到了$1和$2这两个部分,但是看起来转义反斜杠会干扰替换。

我怎样才能得到预期的结果:

"Upper Case String"

【问题讨论】:

  • "$1$L$2" 导致"U$LPPER C$LASE S$LTRING"...
  • 您可能想查看NSString 方法capitalizedString,它应该可以从 Swift 获得。
  • 从NSRegularExpression类参考中的“表3-模板匹配格式”来看,替换模板表达式不支持\L
  • @MattGibson:这很优雅,你也可以直接将它与 Swift Strings 一起使用。谢谢。
  • @nhahtdh 感谢您的产品;完成。

标签: regex swift


【解决方案1】:

许多有用的现有NSString 方法都可以从Swift 中获得。这包括 capitalizedString,它可能会完全按照您的要求进行操作,具体取决于您的要求。

【讨论】:

  • 它适用于 OP 中的特定示例,但是如果您想要一些不同的东西,例如撇号后的大写字母(L'Avion 而不是 L'avion),那么您需要去一个正则表达式。而且我绝对错过了 Swift 中的 \L 和/或 \U :/
【解决方案2】:

据我所知,标题大小写字符串是每个单词的首字母大写的字符串(介词、冠词和连词除外)。所以,代码应该是这样的:

public extension String {
    subscript(range: NSRange) -> Substring {
        get {
            if range.location == NSNotFound {
                return ""
            } else {
                let swiftRange = Range(range, in: self)!
                return self[swiftRange]
            }
        }
    }

    /// Title-cased string is a string that has the first letter of each word capitalised (except for prepositions, articles and conjunctions)
    var localizedTitleCasedString: String {
        var newStr: String = ""

        // create linguistic tagger
        let tagger = NSLinguisticTagger(tagSchemes: [.lexicalClass], options: 0)
        let range = NSRange(location: 0, length: self.utf16.count)
        tagger.string = self

        // enumerate linguistic tags in string
        tagger.enumerateTags(in: range, unit: .word, scheme: .lexicalClass, options: []) { tag, tokenRange, _ in
            let word = self[tokenRange]

            guard let tag = tag else {
                newStr.append(contentsOf: word)
                return
            }

            // conjunctions, prepositions and articles should remain lowercased
            if tag == .conjunction || tag == .preposition || tag == .determiner {
                newStr.append(contentsOf: word.localizedLowercase)
            } else {
                // any other words should be capitalized
                newStr.append(contentsOf: word.localizedCapitalized)
            }
        }
        return newStr
    }
}

【讨论】: