正则表达式在在线工具中工作,但不同意NSRegularExpression


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"))

最新更新