RegEx 在 RegexR 中在线工作,但无法在 NSRegularExpression 中的 iOS 上初始化

RegEx works online in RegexR but fails to initialise on iOS in NSRegularExpression

我有一个正则表达式,旨在从 CocoaPods 定义中提取 git URL。

输入文字如下:

pod 'Alamofire', :git => 'https://github.com/Alamofire/Alamofire.git', :branch => 'dev'

正则表达式如下:

(?<=('Alamofire'.*:git => '))[A-Za-z:/\.]+(?=('{1}))

此正则表达式在 RegexR 上工作正常,请参阅 here,但是当尝试用它初始化 NSRegularExpression 时,会抛出代码 2048 的错误,指出模式无效。通常这是由于缺少转义符,但这里有 none。即使在搜索引擎 iOS 使用的 ICU 正则表达式文档后,我也无法弄清楚问题是什么。

任何想法都会受到欢迎,TIA。

NSRegularExpression 中的后向断言是有限的,不支持其中的 *+ 运算符:

(?<=('Alamofire'.*:git => '))

中的 .* 部分

(?<= ... )

Look-behind assertion. True if the parenthesized pattern matches text preceding the current input position, with the last character of the match being the input character just before the current position. Does not alter the input position. The length of possible strings matched by the look-behind pattern must not be unbounded (no * or + operators.)

Ref: https://developer.apple.com/documentation/foundation/nsregularexpression

您只需要 url,因此只需要简单地模式匹配那部分,而无需首先进行回顾断言。

您不能在带有 ICU 正则表达式的回顾模式中使用未知长度的模式。您的模式在后视中包含 .*,因此它是无效的 ICU regexp(请参阅后视模式匹配的可能字符串的 长度不得无界(无 *+ 运算符。) ICU 回顾文档部分)。

有两种方法:

  • .* 替换为 .{0,x} 其中 x 是您希望将左手模式与右手模式分开的最大字符数,ICU 正则表达式后视允许limiting(或intervalrange)量词,这就是为什么它们也被称为"constrained-width")
  • 重新修改您的模式以使用消费模式而不是环顾四周,用捕获括号包裹您需要提取的部分并修改您的代码以获取第 1 组值。

这里是方法二,推荐:

let str = "pod 'Alamofire', :git => 'https://github.com/Alamofire/Alamofire.git', :branch => 'dev'"
let rng = NSRange(location: 0, length: str.utf16.count)
let regex = try! NSRegularExpression(pattern: "'Alamofire'.*:git\s*=>\s*'([^']+)'")
let matches = regex.matches(in: str, options: [], range: rng)
let group1 = String(str[Range(matches[0].range(at: 1), in: str)!])
print(group1) // => https://github.com/Alamofire/Alamofire.git

参见 regex demo,绿色突出显示的子字符串是您在第 1 组中获得的值。

图案详情:

  • 'Alamofire' - 文字字符串
  • .* - 除换行字符外的任何 0+ 个字符,尽可能多(替换为 .*? 以匹配尽可能少的字符)
  • :git - 文字子串
  • \s*=>\s* - => 包含 0+ 个空格的子字符串
  • '([^']+)' - ',然后是捕获组 #1 匹配 ' 以外的 1+ 个字符,然后是 ' 字符。