2014-09-17 9 views
9

Ich habe Probleme, NSRegularExpression zu bekommen, um Muster auf Zeichenfolgen mit breiteren (?) Unicode-Zeichen in ihnen zusammenzubringen. Es sieht so aus, als ob das Problem der Range-Parameter ist - Swift zählt einzelne Unicode-Zeichen, während Objective-C Strings so behandelt, als ob sie aus UTF-16-Code-Einheiten bestehen.Wie kann ich NSRegularExpression auf Swift-Strings mit Unicode-Zeichen variabler Breite verwenden?

Hier ist mein Test-String und zwei reguläre Ausdrücke:

let dogMatch = dogRegex.firstMatchInString(str, options: nil, 
        range: NSRange(location: 0, length: countElements(str))) 
println(dogMatch?.range) // (0, 3) 

Aber der zweite nicht mit den gleichen Parametern, denn:

let str = "dogcow" 
let dogRegex = NSRegularExpression(pattern: "d.g", options: nil, error: nil)! 
let cowRegex = NSRegularExpression(pattern: "c.w", options: nil, error: nil)! 

ich die erste Regex ohne Probleme mithalten können der Bereich, den ich es sende (0 ... 7) ist nicht lang genug, um die ganze Zeichenfolge bis NSRegularExpression betrifft:

let cowMatch = cowRegex.firstMatchInString(str, options: nil, 
        range: NSRange(location: 0, length: countElements(str))) 
println(cowMatch.range) // nil 

Wenn ich einen anderen Bereich verwenden kann ich das Spiel erfolgreich machen:

let cowMatch2 = cowRegex.firstMatchInString(str, options: nil, 
        range: NSRange(location: 0, length: str.utf16Count)) 
println(cowMatch2?.range) // (7, 3) 

aber dann weiß ich nicht, wie der gefundenen Text aus dem String extrahiert werden, da dieser Bereich außerhalb des Bereichs fällt von die schnelle Schnur.

+1

+ eine für die dogcow Referenz. – devios1

Antwort

10

Es stellt sich heraus, dass Sie Feuer mit Feuer bekämpfen können. Unter Verwendung der utf16Count-Eigenschaft der Swift-native-Zeichenfolge und der substringWithRange:-Methode von NSString - nichtString - erhält das richtige Ergebnis. Hier ist die vollständige Arbeits Code:

let str = "dogcow" 
let cowRegex = NSRegularExpression(pattern: "c.w", options: nil, error: nil)! 

if let cowMatch = cowRegex.firstMatchInString(str, options: nil, 
         range: NSRange(location: 0, length: str.utf16Count)) { 
    println((str as NSString).substringWithRange(cowMatch.range)) 
    // prints "cow" 
} 

(ich dies in den Prozess des Schreibens der Frage herausgefunden, eine für rubber duck debugging punkten.)

+1

Wenn Sie zuerst "let nsstr = str als NSString" konvertieren, dann können Sie einfach 'length: [nstrtr length]' wie in ObjC verwenden. –