do {
// initialization failed, looks like I can not use "\" here
let regex = try NSRegularExpression.init(pattern: "(?<!\)n")
let string = """
aaabbb
zzz
"""
// expect "aaabbbnzzz"
print(regex.stringByReplacingMatches(in: string, options: [], range: NSMakeRange(0, string.count), withTemplate: "\n"))
} catch let error {
print(error)
}
在这里我想替换";\n〃;在我的字符串中\\n〃;,但一开始就失败了,错误消息是
// NSRegularExpression did not recognize the pattern correctly.
Error Domain=NSCocoaErrorDomain Code=2048 "The value “(?<!)
” is invalid." UserInfo={NSInvalidValue=(?<!)
}
regex已经在正则表达式101中进行了测试,所以它是正确的,只是由于某些原因在Swift中不起作用。
我该怎么做?
基于Larme的评论:
在Swift中,字符串中的
(双反斜杠(表示";有一个``,正如您在错误中看到的,您有
(?<!)
,但这意味着您正在转义结束)
,因此您缺少一个结束)
。我想说你应该写"(?<!\\)n"
?
我终于弄清楚发生了什么以及如何修复它。
问题是反斜杠。
在Swift中,双引号内的反斜杠将被视为转义序列,如以下
// won't compile
// error: Invalid escape sequence in literal
let regex = try NSRegularExpression.init(pattern: "(?<!)n")
如果我们再加一个反斜杠,行吗?
不,因为这两个反斜杠将被视为即将结束的单个转义符(。
// compile but get a runtime error
let regex = try NSRegularExpression.init(pattern: "(?<!\)n")
因此出现运行时错误
NSRegularExpression did not recognize the pattern correctly.
Error Domain=NSCocoaErrorDomain Code=2048 "The value “(?<!)
” is invalid." UserInfo={NSInvalidValue=(?<!)
为了表明我们需要的是一个字面上的反斜杠,我们实际上需要4个反斜杠
let regex = try NSRegularExpression.init(pattern: "(?<!\\)n")
前两个反斜杠表示转义字符,后两个表示一个字面反斜杠。
这些看起来很麻烦。
更好的方法
幸运的是,从Swift 5开始,我们可以使用一对#来完成这个
// works like in online tool
let regex = try NSRegularExpression.init(pattern: #"(?<!\)n"#)
另一件事
值得注意的是,正则表达式的初始化并不是唯一需要特殊处理的事情
// withTemplate
print(regex.stringByReplacingMatches(in: string, options: [], range: NSMakeRange(0, string.count), withTemplate: #"\n"#))
// As a comparison, this is OK
print(string.replacingOccurrences(of: "n", with: "\N"))