正则表达式 unicode 在 swift 中不起作用
regular expression unicode does not work in swift
let regex1 = "(\ud83d\udc68)"
let regex2 = "(\ud83d[\udc68-\udc69])"
"".capturedGroupsFull(forRegex: regex1)
// returns 1 match: [(.0 "", .1 {0, 2})]
"".capturedGroupsFull(forRegex: regex2)
// returns nil
为什么第一行 return 匹配一个而第二行不匹配?
- 两个正则表达式在 regex101 上都能正常工作(例如设置为
javascript 并将第二个正则表达式用作
(\ud83d[\udc68-\udc69])
)。
- 我是
使用 Swift 4.0.
- 这个正则表达式
"(\ud83d[\udc68])"
也将
return nil
在 Playground 中测试时。
您可以在下面找到我用来检索匹配项的完整代码。
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
}
}
为什么第一行返回一个匹配而第二行没有匹配?
如前所述,NSRegularExpression
适用于 Unicode 代码点,而(正常)JavaScript 正则表达式适用于 UTF-16 代码单元。
某些模式,如 "\ud83d\udc68"
,由有效的代理对组成,可能会优化为单个 Unicode 代码点 U+1F468,但此功能不是 well-documented,因此您应该不要依赖它,正如您在示例 "(\ud83d[\udc68])"
.
中所见
我建议不要对 \uhhhh
使用代理对,但对 non-BMP 个字符使用 \UHHHHHHHH
(或 \x{hhhh}
)。
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
).
let regex1 = "(\ud83d\udc68)"
let regex2 = "(\ud83d[\udc68-\udc69])"
"".capturedGroupsFull(forRegex: regex1)
// returns 1 match: [(.0 "", .1 {0, 2})]
"".capturedGroupsFull(forRegex: regex2)
// returns nil
为什么第一行 return 匹配一个而第二行不匹配?
- 两个正则表达式在 regex101 上都能正常工作(例如设置为
javascript 并将第二个正则表达式用作
(\ud83d[\udc68-\udc69])
)。 - 我是 使用 Swift 4.0.
- 这个正则表达式
"(\ud83d[\udc68])"
也将 returnnil
在 Playground 中测试时。
您可以在下面找到我用来检索匹配项的完整代码。
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
}
}
为什么第一行返回一个匹配而第二行没有匹配?
如前所述,NSRegularExpression
适用于 Unicode 代码点,而(正常)JavaScript 正则表达式适用于 UTF-16 代码单元。
某些模式,如 "\ud83d\udc68"
,由有效的代理对组成,可能会优化为单个 Unicode 代码点 U+1F468,但此功能不是 well-documented,因此您应该不要依赖它,正如您在示例 "(\ud83d[\udc68])"
.
我建议不要对 \uhhhh
使用代理对,但对 non-BMP 个字符使用 \UHHHHHHHH
(或 \x{hhhh}
)。
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
).