代码之家  ›  专栏  ›  技术社区  ›  Yevgeny Simkin

需要正则表达式来查找两个令牌之间的子字符串

  •  5
  • Yevgeny Simkin  · 技术社区  · 16 年前

    我怀疑这个问题已经在某个地方得到了回答,但我找不到,所以。。。

    我需要从一个更大的字符串中的两个令牌之间提取一个字符串,其中第二个令牌可能会再次出现。..(伪代码…)

    myString = "A=abc;B=def_3%^123+-;C=123;"  ;
    
    myB = getInnerString(myString, "B=", ";" )  ;
    
    method getInnerString(inStr, startToken, endToken){
       return inStr.replace( EXPRESSION, "$1");
    }
    

    所以,当我使用表达式“ .+B=(.+);.+ " 我得到“def_3%^123+-;C=123;”,可能是因为它只是查找'的最后一个实例;在字符串中,而不是在第一个字符串处停止。

    我试着用(?=)来寻找第一个;但它给了我同样的结果。

    我似乎找不到一个regExp引用来解释如何指定“NEXT”令牌而不是末尾的令牌。

    非常感谢大家的帮助。


    关于SO的类似问题:

    3 回复  |  直到 8 年前
        1
  •  7
  •   Evan Fosmark    16 年前

    你使用的是贪婪模式,没有指定 ? 在里面。试试这个:

    ".+B=(.+?);.+" 
    
        2
  •  5
  •   Gumbo    16 年前

    试试这个:

    B=([^;]+);
    

    这与以下各项相匹配 B= ; 除非是a ; 因此,它与以下各项相匹配 B 第一个 ; 此后。

        3
  •  2
  •   Alan Moore Chris Ballance    16 年前

    (这是从评论到埃文回答的对话的延续。)

    以下是应用(更正的)正则表达式时发生的情况:首先 .+ 匹配整个字符串。然后它回溯,放弃刚刚匹配的大部分字符,直到到达 B= 可以匹配。然后 (.+?) 匹配(并捕获)它看到的所有内容,直到下一部分分号可以匹配为止。然后是决赛 .+ 吞噬剩下的角色。

    你真正感兴趣的是“B=”和“;”以及它们之间的任何东西,那么为什么要匹配字符串的其余部分呢?您必须这样做的唯一原因是,您可以用捕获组的内容替换整个字符串。但是,如果您可以直接访问组的内容,为什么还要费心这样做呢?这是一个演示(用Java,因为我不知道你使用的是哪种语言):

    String s = "A=abc;B=def_3%^123+-;C=123;";
    
    Pattern p = Pattern.compile("B=(.*?);");
    Matcher m = p.matcher(s);
    if (m.find())
    {
      System.out.println(m.group(1));
    }
    

    当“查找”更简单时,为什么要“替换”呢?可能是因为你的API使它更容易;这就是为什么我们用Java来做。Java在其String类中有几个面向正则表达式的便利方法: replaceAll() , replaceFirst() , split() ,以及 matches() (返回 true 如果正则表达式与 整个 字符串),但不是 find() 。而且也没有方便的方法来访问捕获组。我们无法像这样优雅的Perl单行程序:

    print $1 if 'A=abc;B=def_3%^123+-;C=123;' =~ /B=(.*?);/;
    

    …所以我们满足于这样的黑客:

    System.out.println("A=abc;B=def_3%^123+-;C=123;"
        .replaceFirst(".+B=(.*?);.+", "$1"));
    

    需要明确的是,我并不是说不要使用这些技巧,也不是说埃文的答案有什么问题——没有。我只是觉得我们应该理解 为什么? 我们使用它们,以及我们在使用时所做的权衡。