当源包含unicode字符时,Swift正则表达式匹配失败

时间:2015-04-20 19:19:02

标签: regex swift xcode6 nsregularexpression

我正在尝试使用NSRegularExpression进行简单的正则表达式匹配,但是当源包含多字节字符时,我在匹配字符串时遇到一些问题:

let string = "D 9"

// The following matches (any characters)(SPACE)(numbers)(any characters)
let pattern = "([\\s\\S]*) ([0-9]*)(.*)"

let slen : Int = string.lengthOfBytesUsingEncoding(NSUTF8StringEncoding)

var error: NSError? = nil

var regex = NSRegularExpression(pattern: pattern, options: NSRegularExpressionOptions.DotMatchesLineSeparators, error: &error)

var result = regex?.stringByReplacingMatchesInString(string, options: nil, range: NSRange(location:0,
length:slen), withTemplate: "First \"$1\" Second: \"$2\"")

上面的代码按预期返回“D”和“9”

如果我现在更改第一行以包含英国“英镑”货币符号,如下所示:

let string = "£ 9"

然后匹配不起作用,即使表达式的([\\s\\S]*)部分仍然匹配任何前导字符。

我知道£符号将占用两个字节但是通配符前导匹配应该忽略那些不应该的吗?

有人能解释一下这里发生了什么吗?

1 个答案:

答案 0 :(得分:8)

这可能令人困惑。 stringByReplacingMatchesInString()的第一个参数是从NSString映射而来的 目标-C到String在Swift中,但range:参数仍然是 NSRange。因此,您必须以单位指定范围 由NSString使用(这是UTF-16代码点的数量):

var result = regex?.stringByReplacingMatchesInString(string,
        options: nil,
        range: NSRange(location:0, length:(string as NSString).length),
        withTemplate: "First \"$1\" Second: \"$2\"")

或者您可以使用count(string.utf16) 而不是(string as NSString).length

完整示例:

let string = "£ 9"

let pattern = "([\\s\\S]*) ([0-9]*)(.*)"
var error: NSError? = nil
let regex = NSRegularExpression(pattern: pattern,
        options: NSRegularExpressionOptions.DotMatchesLineSeparators,
        error: &error)!

let result = regex.stringByReplacingMatchesInString(string,
    options: nil,
    range: NSRange(location:0, length:(string as NSString).length),
    withTemplate: "First \"$1\" Second: \"$2\"")
println(result)
// First "£" Second: "9"