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

如何使用Swift NSRegularExpression获取大写字母?,swift,nsregularexpression,Swift,Nsregularexpression,我有这样一个字符串: “te_st”并希望将后跟字符的所有下划线替换为该字符的大写版本 从“te_st”-->找到(正则表达式:“)-------替换为下一个字符(+大写(“s”)-->“s”)----------->“teSt” 从“测试”-->到“测试” 从“\u he\u l\u lo”-->到“HeLLo” 从“一个字符串”-->到“另一个字符串” …但我无法使用Swift的NSRegularExpression使其真正工作,就像这个小剪子所做的那样: var result = "t

我有这样一个字符串:

“te_st”
并希望将
后跟字符的所有下划线替换为该字符的大写版本


“te_st”
-->找到(正则表达式:
)-------替换为下一个字符(+大写(
“s”
)-->
“s”
)----------->
“teSt”



“测试”
-->到
“测试”

“\u he\u l\u lo”
-->到
“HeLLo”

“一个字符串”
-->到
“另一个字符串”

…但我无法使用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()))
var result=“te_st”//应测试结果

result=try!NSRegularExpression(模式:“*”)。stringByReplacingMatches(in:result,range:NSRange(0..您可以将string
range(of:,options:,range:)
方法与
一起使用。regularExpression
选项匹配
“\uz]”
并将以相反顺序找到的范围迭代的子范围替换为范围小写大写后的索引处的字符:

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"
let string=“an\u o\u t\u h\u er\u strin\g”
让regex=“\uz[a-z]”
var start=string.startIndex
变量范围:[范围]=[]

虽然让range=string.range(of:regex,options:.regularExpression,range:start..这里有一个使用NSRegularExpression的实现。我使用组匹配来获取u之后的字符并将其大写,然后替换字符串

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
还有一个没有使用正则表达式,我对这个方法做了扩展,这个扩展也可以重用

extension String {

  func indexes(of character: String) -> [Index] {
    precondition(character.count == 1, "character should be single letter string")

    return enumerated().reduce([]) { (partial, component) in

      let currentIndex = index(startIndex,
                               offsetBy: component.offset)
      return String(self[currentIndex]) == character
                                  ? partial + [currentIndex]
                                  : partial
    }
  }

  func capitalizeLetter(after indexes: [Index]) -> String {
    var modifiedString = self

    for currentIndex in indexes {

      guard let letterIndex = index(currentIndex,
                                           offsetBy: 1,
                                           limitedBy: endIndex)
        else { continue }

      let range = letterIndex ... letterIndex

      modifiedString = modifiedString.replacingCharacters(in: range,
                                                          with: self[range].capitalized)
    }

    return modifiedString
  }
}

let string = "an_o_t_h_er_strin_g"
let newString = string.capitalizeLetter(after: string.indexes(of: "_"))
                      .replacingOccurrences(of: "_",with: "")

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

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

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())
扩展字符串{
func toCamelCase()->字符串{
让expr=try!NSRegularExpression(模式:“([a-z])”)
var res=自我

对于expr.matches中的match(在:self,range:NSRange(0..中),问题是它正在将字符串“$1”转换为大写(毫不奇怪,只有“$1”)并使用“$1”作为模板。如果要使用regex,则必须自己通过匹配进行枚举

另一种方法是将字符串拆分为
\uu
个字符和每个子字符串(第一个除外)的第一个大写字符,然后使用
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)...]
    }
}

如果要使用
NSRegularExpression
进行某种动态转换,可以将
NSRegularExpression
子类化并覆盖
replacementString(for:in:offset:template:)

class to CamelRegularRexpression:nsrRegularRexpression{
重写func replacementString(对于结果:NSTextCheckingResult,in-string:string,offset:Int,template temp:string)->string{
如果let range=range(result.range(at:1),in:string){
返回字符串[range]。大写()
}否则{
返回super.replacementString(for:result,in:string,偏移量:0,模板:templ)
}
}
}
func-toCamelCase(uinput:String)->String{//如果您愿意,请将其设置为字符串扩展名。。。
让regex=try!ToCamelRegularExpression(模式:“(.)”)
返回regex.stringByReplacingMatches(in:input,options:[],range:NSRange(0..teSt
print(toCamelCase(“\u he\u l\u lo”)/->您好
打印(到CAMELCASE(“一个字符”)//>另一个字符串

Working-看起来不错。感谢Sandeep
String。字符串扩展方法中的Index
是多余的。
func Index(字符:String)->[Index]
和Index有一个特定的方法来偏移一个名为
Index(after:)
Index(after:currentIndex)的位置
@LeoDabus您看到的任何其他内容都可以改进。请编写它,我可以从中学习:)如果indexOfLetterAfter>=endIndex{continue},您可以删除
,如果您使用
索引(,offsetBy:,limitedBy:)
使用字符串
endIndex
作为限制。它返回可选索引,但与apple“$n”的正则表达式文档中的索引一样将替换为结果。在这种情况下,$1将替换为第一个匹配项及其字符串。因此,为什么我们不能对字符串使用方法?无需为选项传递空数组,因为它已经是两个选项中的默认值cases@MuhammadZohaibEhsan因为需求不是简单的替换。替换需要转换为大写。这不能用简单的正则表达式来完成。因此我们不能在模板上使用方法。替换字符串应该用作模板。结果不能被操纵?@Muhammadzohaibehansan不,没有简单的语法来操纵模板结果。OP试图用
uppercased
来实现这一点。
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