如何使用Swift NSRegularExpression获取大写字母?

时间:2018-01-08 18:13:09

标签: swift nsregularexpression

我有一个这样的字符串:

"te_st"并希望将 all underscores followed by a character 替换为此字符的大写版本。

来自"te_st" - >找到(正则表达式:"_.")--------替换为下一个字符(+大写字母("s" - > "S")--------> "teSt"


来自"te_st" --->到"teSt"
来自"_he_l_lo" --->到"HeLLo"
来自"an_o_t_h_er_strin_g" --->到"anOTHErStrinG"

...但是我无法真正使用Swift' NSRegularExpression这样的小剪辑:

var result = "te_st" // result should be teSt
result = try! NSRegularExpression(pattern: "_*").stringByReplacingMatches(in: result, range: NSRange(0..<result.count), withTemplate: ("$1".uppercased()))

5 个答案:

答案 0 :(得分:1)

这是使用NSRegularExpression的一个实现。我使用组匹配来获取_之后的字符并将其大写并替换字符串。

from airflow import configuration

def slack_failed_task(context):
    link = '<{base_url}/admin/airflow/log?dag_id={dag_id}&task_id={task_id}&execution_date={execution_date}|logs>'.format(
        base_url=configuration.get('webserver', 'BASE_URL'),
        dag_id=context['dag'].dag_id,
        task_id=context['task_instance'].task_id,
        execution_date=context['ts']))  # equal to context['execution_date'].isoformat())

    failed_alert = SlackAPIPostOperator(
        task_id='slack_failed',
        channel="#mychannel",
        token="...",
        text=':red_circle: Failure on: ' + 
             str(context['dag']) +
             '\nRun ID: ' + str(context['run_id']) +
             '\nTask: ' + str(context['task_instance']) +
             '\nSee ' + link + ' to debug')
    return failed_alert.execute(context=context)

这是另一个不使用正则表达式的人。我为方法做了扩展,也可以重用。

func capitalizeLetterAfterUnderscore(string: String) -> String {
  var capitalizedString = string

  guard let regularExpression = try?  NSRegularExpression(pattern: "_(.)") else {
                                                            return capitalizedString
  }

  let matches = regularExpression.matches(in: string,
                                          options: .reportCompletion,
                                          range: NSMakeRange(0, string.count))

  for match in matches {
      let groupRange = match.range(at: 1)
      let index = groupRange.location

      let characterIndex = string.index(string.startIndex,
                                          offsetBy: index)
      let range = characterIndex ... characterIndex

      let capitalizedCharacter = String(capitalizedString[characterIndex]).capitalized
      capitalizedString = capitalizedString.replacingCharacters(in: range,
                                                                with: capitalizedCharacter)
  }

  capitalizedString = capitalizedString.replacingOccurrences(of: "_", with: "")
  return capitalizedString
}



capitalizeLetterAfterUnderscore(string: "an_o_t_h_er_strin_g") // anOTHErStrinG

答案 1 :(得分:1)

没有常规语法将匹配转换为大写。您发布的代码正在尝试将字符串$1转换为大写,当然只是$1。它不会尝试在运行时转换$1匹配所代表的值。

这是另一种使用正则表达式查找_后跟小写字母的方法。这些被枚举并替换为大写字母。

extension String {
    func toCamelCase() -> String {
        let expr = try! NSRegularExpression(pattern: "_([a-z])")
        var res = self
        for match in expr.matches(in: self, range: NSRange(0..<res.count)).reversed() {
            let range = Range(match.range, in: self)!
            let letterRange = Range(match.range(at: 1), in: self)!
            res.replaceSubrange(range, with: self[letterRange].uppercased())
        }

        return res
    }
}

print("te_st".toCamelCase())
print("_he_l_lo".toCamelCase())
print("an_o_t_h_er_strin_g".toCamelCase())

输出:

  

测试
  你好
  anOTHErStrinG

答案 2 :(得分:0)

您可以使用带有range(of:, options:, range:)选项的字符串.regularExpression方法来匹配"_[a-z]"的出现次数,并将范围内的索引处的字符替换为相反顺序的子范围。下限大写:

let string = "an_o_t_h_er_strin_g"
let regex = "_[a-z]"
var start = string.startIndex
var ranges:[Range<String.Index>] = []

while let range = string.range(of: regex, options: .regularExpression, range: start..<string.endIndex) {
    start = range.upperBound
    ranges.append(range)
}
var finalString = string
for range in ranges.reversed() {
    finalString.replaceSubrange(range, with: String(string[string.index(after: range.lowerBound)]).uppercased())
}
print(finalString)   // "anOTHErStrinG\n"

答案 3 :(得分:0)

问题是它将字符串“$ 1”转换为大写字母(不出所料,只改为“$ 1”)并使用“$ 1”作为模板。如果你想使用正则表达式,你必须自己枚举匹配。

另一种方法是将字符串分割为_个字符,并将每个子字符串的第一个字符(第一个字符除外)大写,并使用reduce将其重新连接在一起:

let input = "te_st"

let output = input.components(separatedBy: "_").enumerated().reduce("") { $0 + ($1.0 == 0 ? $1.1 : $1.1.uppercasedFirst()) }

或者,如果你的目标不是像大多数正则表达式一样编写代码,我们可以使它更清晰:

let output = input
    .components(separatedBy: "_")
    .enumerated()
    .reduce("") { result, current in
        if current.offset == 0 {
            return current.element      // because you don’t want the first component capitalized
        } else {
            return result + current.element.uppercasedFirst()
        }
}

导致:

  

测试

注意,使用此扩展名来大写第一个字符:

extension String {
    func uppercasedFirst(with locale: Locale? = nil) -> String {
        guard count > 0 else { return self }
        return String(self[startIndex]).uppercased(with: locale) + self[index(after: startIndex)...]
    }
}

答案 4 :(得分:0)

如果您希望使用NSRegularExpression进行某种动态转换,则可以继承NSRegularExpression并覆盖replacementString(for:in:offset:template:)

class ToCamelRegularExpression: NSRegularExpression {
    override func replacementString(for result: NSTextCheckingResult, in string: String, offset: Int, template templ: String) -> String {
        if let range = Range(result.range(at: 1), in: string) {
            return string[range].uppercased()
        } else {
            return super.replacementString(for: result, in: string, offset: 0, template: templ)
        }
    }
}

func toCamelCase(_ input: String) -> String { //Make this a String extension if you prefer...
    let regex = try! ToCamelRegularExpression(pattern: "_(.)")
    return regex.stringByReplacingMatches(in: input, options: [], range: NSRange(0..<input.utf16.count), withTemplate: "$1")
}
print(toCamelCase("te_st")) //-> teSt
print(toCamelCase("_he_l_lo")) //-> HeLLo
print(toCamelCase("an_o_t_h_er_strin_g")) //-> anOTHErStrinG