如何在具有可变宽度 Unicode 字符的 Swift 字符串上使用 NSRegularExpression?

Posted

技术标签:

【中文标题】如何在具有可变宽度 Unicode 字符的 Swift 字符串上使用 NSRegularExpression?【英文标题】:How can I use NSRegularExpression on Swift strings with variable-width Unicode characters? 【发布时间】:2014-11-11 00:19:33 【问题描述】:

我无法让NSRegularExpression 匹配带有更宽 (?) Unicode 字符的字符串上的模式。看起来问题出在 range 参数上——Swift 计算单个 Unicode 字符,而 Objective-C 将字符串视为由 UTF-16 代码单元组成。

这是我的测试字符串和两个正则表达式:

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

我可以毫无问题地匹配第一个正则表达式:

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

但是第二个使用相同的参数失败,因为就NSRegularExpression 而言,我发送它的范围 (0...7) 不足以覆盖整个字符串:

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

如果我使用不同的范围,我可以使匹配成功:

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

但是我不知道如何从字符串中提取匹配的文本,因为该范围超出了 Swift 字符串的范围。

【问题讨论】:

+one 作为 dogcow 参考。 【参考方案1】:

事实证明,你可以以火攻毒。使用 Swift 原生字符串的 utf16Count 属性和 NSStringsubstringWithRange: 方法 -- not String -- 得到正确的结果。这是完整的工作代码:

let str = "dog??cow"
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"

(我在写问题的过程中发现了这一点;rubber duck debugging 得一分。)

【讨论】:

如果你先转换let nsstr = str as NSString,那么你可以像在ObjC中那样简单地使用length: [nsstr length]

以上是关于如何在具有可变宽度 Unicode 字符的 Swift 字符串上使用 NSRegularExpression?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Python 3 中获得组合 Unicode 字符的显示宽度?

如何绘制具有可变笔画宽度的路径

打开具有可变宽度的关闭侧菜单(在 xcode 中)

具有可变宽度单元格的 UITableView

从 Python 字符串中删除零宽度空格 unicode 字符

如何使用 AutoLayout 配置视图宽度固定宽度和可变高度