代码之家  ›  专栏  ›  技术社区  ›  Mischa

如何搜索在字符串的某个索引之前开始的正则表达式匹配项?

  •  0
  • Mischa  · 技术社区  · 5 年前

    假设我有一个正则表达式

    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之前 .


    上面描述的行为不同于只搜索字符串的子范围。原因如下:

    –应匹配:

    以下示例应在[59]范围内生成匹配,因为匹配在最大索引(=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 
    

    我怎样才能做到这一点?

    0 回复  |  直到 5 年前
        1
  •  1
  •   Aaron Cyrman    5 年前

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

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

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

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

    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个 .

    希望这对你有用。