5

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

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

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;” 大概是因为它只是寻找';'的最后一个实例 在字符串中,而不是停在第一个出现的地方。

我尝试使用 (?=) 来搜索第一个 ';' 但它给了我同样的结果。

我似乎找不到一个正则表达式参考来解释如何指定“NEXT”令牌而不是最后的那个。

非常感谢任何和所有帮助。


关于SO的类似问题:

4

3 回答 3

7

您通过不指定其中来使用贪婪模式?。试试这个:

".+B=(.+?);.+" 
于 2009-01-28T21:58:18.447 回答
5

试试这个:

B=([^;]+);

这匹配 和 之间的所有内容B=;除非它是;. 所以它匹配之后B=的所有内容;

于 2009-01-28T21:58:03.767 回答
2

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

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

为了清楚起见,我并不是说不要使用这些技巧,或者埃文的回答有什么问题——没有。我只是认为我们应该了解我们为什么使用它们,以及我们在使用它们时要做出哪些权衡。

于 2009-01-30T06:36:22.090 回答