【问题标题】:How can I search for a Regular Expression match that begins before a certain index of a string?如何搜索在字符串的某个索引之前开始的正则表达式匹配?
【发布时间】:2019-07-18 09:45:30
【问题描述】:

假设我有一个正则表达式

let regexString = "\\s{1,3}(---+)\\s*"
let regex = try? NSRegularExpression(pattern: regexString)

还有一个字符串

let string = "Space --- the final frontier --- these are the voyages..."

让我们进一步假设该字符串确实很长,并且在省略号 (...) 之后延续了数千个字符。

现在我想找到正则表达式 regex 的第一个匹配项,但出于效率原因,我想在某个索引后停止搜索

示例:

index:  0  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
string: S  p  a  c  e     -  -  -     t  h  e     f  i  n  a  l     f  r  o  n  t  i  e  r
range:  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  ⬆︎ -  -  -  -  -  -  -  -  -  -  -  -
                                                     max 

这意味着我只在字符串中搜索一个正则表达式匹配开始在索引15之前


上述行为与仅搜索字符串的子范围不同。原因如下:

✅ 应该匹配:

以下示例应在 [5–9] 范围内产生匹配,因为匹配在最大索引 (= 7) 之前开始。

index:  0  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
string: S  p  a  c  e     -  -  -     t  h  e     f  i  n  a  l     f  r  o  n  t  i  e  r
range:  +  +  +  +  +  +  +  ⬆︎ -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -
                             max 

❎ 应该,但不匹配:

如果我只搜索到最大索引 (= 7) 的子字符串,正则表达式将无法匹配,因为部分匹配会被截断。

index:  0  1  2  3  4  5  6  7  
string: S  p  a  c  e     -  -  
range:  +  +  +  +  +  +  +  ⬆︎ 
                             max 

我怎样才能做到这一点?

【问题讨论】:

标签: swift regex string nsregularexpression


【解决方案1】:

由于您使用的是捕获组,我假设这是您要查找的字符串。您可以将表达式更改为:^.{0,6}\\s{1,3}(---+)\\s*。我添加了以下内容:

  • ^ 字符串开头。
  • 。{0,6} 匹配零到六个字符。

像这样更改表达式将匹配您要查找的内容,如果它最多从位置 6 开始,您的原始表达式将匹配,这是您的 ma​​x。不同之处在于整个匹配包含那些可选字符,但第一个捕获组将只包含您要查找的破折号。

我在操场上使用以下代码来测试新表达式:

let regexString = "^.{0,6}\\s{1,3}(---+)\\s*"
let regex = try? NSRegularExpression(pattern: regexString)
let string = "Space --- the final frontier --- these are the voyages of the     
             starship Enterprise. Its continuing mission: to explore strange 
             new worlds. To seek out new life and new civilizations. To boldly   
             go where no one has gone before!"

let matches = regex?.matches(in: string, options: [], range: NSRange(location: 0, length: string.count))
if let firstMatch = matches?.first {
    print("Whole regex match starts at index: \(firstMatch.range.lowerBound)")
    print("Whole match: \(String(string[Range(firstMatch.range, in: string)!]))")
    print("Capture group start at index: \(firstMatch.range(at: 1).lowerBound)")
    print("Capture group string: \(String(string[Range(firstMatch.range(at: 1), in: string)!]))")
} else {
    print("No matches")
}

运行上面的代码,结果如下:

整个正则表达式匹配从索引:0开始

整场比赛:空格---

捕获组从索引开始:6

捕获组字符串:---

如果string 像这样更改:let string = "The space --- the final frontier --- these are the ... 结果是:

没有匹配项

因为 \\s{1,3} 从索引 10 开始。

希望这对你有用。

【讨论】:

  • 绝妙的答案——尤其是拿我的那个字符串例子来说。 ;) 谢谢!我想知道为什么我没有想到这一点;我必须不使用正则表达式... ;)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-09-11
相关资源
最近更新 更多