【问题标题】:regular expression unicode does not work in swift正则表达式 unicode 在 swift 中不起作用
【发布时间】:2018-09-08 18:15:16
【问题描述】:
let regex1 = "(\\ud83d\\udc68)"
let regex2 = "(\\ud83d[\\udc68-\\udc69])"

"????".capturedGroupsFull(forRegex: regex1)
// returns 1 match: [(.0 "????", .1 {0, 2})]
"????".capturedGroupsFull(forRegex: regex2)
// returns nil

为什么第一行返回一个匹配而第二行不匹配?

  • 两个正则表达式都可以在 regex101 上正常工作(例如,设置为 javascript 并使用第二个正则表达式作为(\ud83d[\udc68-\udc69]))。
  • 我是 使用 Swift 4.0。
  • 这个正则表达式"(\\ud83d[\\udc68])" 也将 在 Playground 中测试时返回 nil

您可以在下面找到我用来检索匹配项的完整代码。

extension String {
    func capturedGroupsFull(forRegex regex: String) -> [(String, NSRange)]? {
        let expression: NSRegularExpression
        do {
            expression = try NSRegularExpression(pattern: regex, options: [.caseInsensitive])
        } catch {
            return nil
        }
        let nsString = self as NSString
        let matches = expression.matches(in: self, options: [], range: NSRange(location:0, length: nsString.length))
        guard let match = matches.first else { return nil }
        var results = [(String, NSRange)]()
        for match in matches {
            let range = match.range
            let matchedString = nsString.substring(with: range)
            results.append((matchedString, range))
        }
        return results
    }
}

【问题讨论】:

  • 您可以链接 regex101 btw。只需点击分享正则表达式
  • @chrisz 谢谢,更新了链接。你知道为什么它不能使用我的代码吗?
  • 哪个版本的 Swift?
  • @chrisz swift 4.0
  • 原因可能是 NSRegularExpression 在 Unicode 标量而不是 UTF-16 代码单元上运行。使用regex2 = "([\\ud83d\\udc68-\\ud83d\\udc69])",您将获得预期的结果。

标签: swift regex unicode emoji nsregularexpression


【解决方案1】:

为什么第一行返回一个匹配而第二行不匹配?

如前所述,NSRegularExpression 适用于 Unicode 代码点,而(正常)JavaScript 正则表达式适用于 UTF-16 代码单元。

"\\ud83d\\udc68" 这样由有效代理对组成的模式可能会优化为单个 Unicode 代码点 U+1F468,但此功能没有详细记录,因此您不应依赖它,因为您在示例中找到了 "(\\ud83d[\\udc68])"


我建议不要将代理对与\uhhhh 一起使用,而是将\UHHHHHHHH(或\x{hhhh})用于非BMP 字符。

let regex1 = "(\\U0001F468)" //or "(\\x{1F468})"
let regex2 = "([\\U0001F468-\\U0001F469])" // or "([\\x{1F468}-\\x{1F469}])"

"?".capturedGroupsFull(forRegex: regex1)
// -> [(.0 "?", .1 {0, 2})]
"?".capturedGroupsFull(forRegex: regex2)
// -> [(.0 "?", .1 {0, 2})]

最近的 JavaScript 正则表达式接受 u 选项以使其与 Unicode 代码点一起使用,试试这些:

/(\u{1F468})/u
/([\u{1F468}-\u{1F469}])/u

您可以使用 JavaScript 语法轻松测试您的正则表达式模式,并将其转换为 NSRegularExpression 语法,方法是将 \u 替换为 \x(并删除 //u)。

【讨论】:

  • 有没有办法让NSRegularExpression 在UTF-16 代码单元上工作?我有一个巨大的正则表达式,需要处理 UTF-16 代码单元,重写该正则表达式是不可行的。
  • @KaraBenNemsi,没有。
猜你喜欢
  • 2013-09-08
  • 1970-01-01
  • 2018-02-27
  • 2018-05-08
  • 2023-03-23
  • 1970-01-01
  • 2017-02-07
  • 2020-07-08
  • 2020-04-02
相关资源
最近更新 更多