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

时间:2009-01-28 21:56:13

标签: regex regex-greedy

我怀疑这已经在某处得到了解答,但我找不到它,所以......

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

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 个答案:

答案 0 :(得分:7)

您使用的是贪婪模式,但未在其中指定?。试试这个:

".+B=(.+?);.+" 

答案 1 :(得分:5)

试试这个:

B=([^;]+);

这符合B=;之间的所有内容,除非它是;。因此,它会匹配B=与之后的第一个;之间的所有内容。

答案 2 :(得分:2)

(这是评论与Evan回答的对话的延续。)

以下是应用(更正的)正则表达式时会发生的情况:首先,.+匹配整个字符串。然后它回溯,放弃它刚刚匹配的大部分字符,直到它到达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"));

为了清楚起见,我并不是说不要使用这些黑客,或者说Evan的回答有什么问题 - 没有。我认为我们应该理解为什么我们使用它们,以及我们在做什么时做出的权衡。