Регулярное выражение matchInString в Swift 2
toCamel()
Функция в этом расширении String должна удалить _
за которым следует символ в середине строки, и замените два символа на верхний регистр.
public extension String {
public func rangeFromNSRange(aRange: NSRange) -> Range<String.Index> {
let s = advance(self.startIndex, aRange.location)
let e = advance(self.startIndex, aRange.location + aRange.length)
return s..<e
}
public var ns : NSString {return self as NSString}
public subscript (aRange: NSRange) -> String? {
get {return self.substringWithRange(self.rangeFromNSRange(aRange))}
}
public var cdr: String {return isEmpty ? "" : String(characters.dropFirst())}
public func toCamel() throws -> String {
var s = self
let regex = try NSRegularExpression(pattern: "_.", options: [])
let matches = regex.matchesInString(s, options:[], range:NSMakeRange(0, s.ns.length)).reverse()
for match in matches {
print("match = \(s[match.range]!)")
let matchRange = s.rangeFromNSRange(match.range)
let uc = s[match.range]!.uppercaseString.cdr
s.replaceRange(matchRange, with: uc)
}
if s.hasPrefix("_") {s = s.cdr}
return s
}
}
Дело в том, что matchesInString
не возвращает совпадения, где _
уже является частью предыдущего матча. И, таким образом, это дает следующие результаты:
try "hello_world".toCamel() //"helloWorld"
try "hello__world".toCamel() //"hello_world"
try "hello___world".toCamel() //"hello_World"
Как обойти это?
3 ответа
Измените свой шаблон на _+(.)
, Это соответствует одному или нескольким подчеркиваниям, за которыми следует другой символ. Круглые скобки помещают этого персонажа в группу захвата. Вы можете вернуть захваченного персонажа с помощью rangeAtIndex
public func toCamel() throws -> String {
var s = self
let regex = try NSRegularExpression(pattern: "_+(.)", options: [])
let matches = regex.matchesInString(s, options:[], range:NSMakeRange(0, s.ns.length)).reverse()
for match in matches {
print("match = \(s[match.range]!)")
let matchRange = s.rangeFromNSRange(match.range) // the whole match range
let replaceRange = match.rangeAtIndex(1) // range of the capture group
let uc = s[replaceRange]!.uppercaseString
s.replaceRange(matchRange, with: uc)
}
if s.hasPrefix("_") {s = s.cdr}
return s
}
Примеры:
"hello_world".toCamel() // helloWorld
"hello___world".toCamel() // helloWorld
"hello_beautiful____world".toCamel() // helloBeautifulWolrd
Обновление для Swift 2.1.1
public extension String {
public func rangeFromNSRange(aRange: NSRange) -> Range<String.Index> {
let s = self.startIndex.advancedBy(aRange.location)
let e = self.startIndex.advancedBy(aRange.location + aRange.length)
return s..<e
}
public var ns : NSString {return self as NSString}
public subscript (aRange: NSRange) -> String? {
get {return self.substringWithRange(self.rangeFromNSRange(aRange))}
}
public var cdr: String {return isEmpty ? "" : String(characters.dropFirst())}
public func toCamel() throws -> String {
var s = self
let regex = try NSRegularExpression(pattern: "_+(.)", options: [])
let matches = regex.matchesInString(s, options:[], range:NSMakeRange(0, s.ns.length)).reverse()
for match in matches {
print("match = \(s[match.range]!)")
let matchRange = s.rangeFromNSRange(match.range) // the whole match range
let replaceRange = match.rangeAtIndex(1) // range of the capture group
let uc = s[replaceRange]!.uppercaseString
s.replaceRange(matchRange, with: uc)
}
if s.hasPrefix("_") {s = s.cdr}
return s
}
}
В вашем коде есть две проблемы.
Во-первых, регулярное выражение, соответствующее вашему требованию, должно быть _+[^_]{1}
,
Второй в вашем cdr
компьютерная собственность, String(characters.dropFirst())
исключить только первое _
персонаж. Вы можете использовать String(characters.suffix(1))
Отредактированный код:
public extension String {
public func rangeFromNSRange(aRange: NSRange) -> Range<String.Index> {
let s = advance(self.startIndex, aRange.location)
let e = advance(self.startIndex, aRange.location + aRange.length)
return s..<e
}
public var ns : NSString {return self as NSString}
public subscript (aRange: NSRange) -> String? {
get {return self.substringWithRange(self.rangeFromNSRange(aRange))}
}
public var cdr: String {return isEmpty ? "" : String(characters.suffix(1))}
public func toCamel() throws -> String {
var s = self
let regex = try NSRegularExpression(pattern: "_+[^_]{1}", options: [])
let matches = regex.matchesInString(s, options:[], range:NSMakeRange(0, s.ns.length)).reverse()
for match in matches {
print("match = \(s[match.range]!)")
let matchRange = s.rangeFromNSRange(match.range)
let uc = s[match.range]!.uppercaseString.cdr
s.replaceRange(matchRange, with: uc)
}
if s.hasPrefix("_") {s = s.cdr}
return s
}
}
Я проверил это на детской площадке.
Пытаться NSRegularExpression(pattern: "_+.", options: [])
Вы должны также прочитать Ссылку класса NSRegularExpression.
+
Совпадение 1 или более раз. Матч столько раз, сколько возможно.