RegEx可在RegexR中在线运行,但无法在iOS上的NSRegularExpression中初始化

时间:2019-03-07 08:15:37

标签: ios regex 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代码,表明该模式无效。通常这是由于缺乏逃生通道,但这里没有。即使拖曳了iOS使用的引擎ICU regex文档,我也无法解决问题所在。

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

2 个答案:

答案 0 :(得分:0)

NSRegularExpression中的后向声明是有限的,并且不支持其中的*+运算符:

.*中的(?<=('Alamofire'.*:git => '))部分

  

(?<= ...)

     

后置断言。如果带括号的模式与文本匹配,则为真   在当前输入位置之前,最后一个字符   match是当前位置之前的输入字符。是否   不改变输入位置。可能匹配的字符串的长度   后向模式所构成的对象不能无界(没有*或+   运算符。)

     

参考:https://developer.apple.com/documentation/foundation/nsregularexpression

您只希望url如此简单地仅匹配该部分,而无需首先使用后置断言。

答案 1 :(得分:0)

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

有两种方法:

  • .*替换为.{0,x},其中x是您希望将左侧模式与右侧模式分开的最大字符数,ICU regex后面允许 limiting (或 interval range )量词,这就是为什么它们也被称为“约束宽度”的原因
  • 重新修改模式以使用消耗模式而不是环顾四周,用括号捕获要提取的部分,并修改代码以获取组1值。

这里是方法2,建议:

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个以上的字符,然后匹配一个'字符。