需要正则表达式来查找两个标记之间的子字符串
我怀疑这个问题已经在某处得到了回答,但我找不到它,所以...
我需要从一个较大字符串中的两个标记之间提取一个字符串,其中第二个标记可能会再次出现,这意味着...(伪代码...)
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”标记而不是最后的标记。
非常感谢任何和所有帮助。
类似的问题:
- 正则表达式:提取字符串中两个标签之间的子字符串
- 正则表达式替换字符串中的所有 \n,但不替换 [code] [/code] 标记内的内容
- 使用正则表达式调用替换分隔符内的模式
- < a href="https://stackoverflow.com/questions/299942/regex-matching-html-tags-and-extracting-text">RegEx 匹配 HTML 标签并提取文本
I suspect this has already been answered somewhere, but I can't find it, so...
I need to extract a string from between two tokens in a larger string, in which the second token will probably appear again meaning... (pseudo code...)
myString = "A=abc;B=def_3%^123+-;C=123;" ;
myB = getInnerString(myString, "B=", ";" ) ;
method getInnerString(inStr, startToken, endToken){
return inStr.replace( EXPRESSION, "$1");
}
so, when I run this using expression ".+B=(.+);.+
"
I get "def_3%^123+-;C=123;" presumably because it just looks for the LAST instance of ';' in the string, rather than stopping at the first one it comes to.
I've tried using (?=) in search of that first ';' but it gives me the same result.
I can't seem to find a regExp reference that explains how one can specify the "NEXT" token rather than the one at the end.
any and all help greatly appreciated.
Similar question on SO:
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
您通过未在其中指定
?
来使用贪婪模式。 尝试这个:You're using a greedy pattern by not specifying the
?
in it. Try this:试试这个:
这匹配
B=
和;
之间的所有内容,除非它是;
。 因此它匹配B=
和其后第一个;
之间的所有内容。Try this:
This matches everything between
B=
and;
unless it is a;
. So it matches everything betweenB=
and the first;
thereafter.(这是从评论到 Evan 的回答的对话的延续。)
以下是应用(更正的)正则表达式时会发生的情况:首先,
.+
匹配整个字符串。 然后它回溯,放弃刚刚匹配的大部分字符,直到到达B=
可以匹配的位置。 然后(.+?)
匹配(并捕获)它看到的所有内容,直到下一部分(分号)可以匹配。 然后最后的.+
吞噬了剩余的字符。您真正感兴趣的是“B=”和“;” 以及它们之间的任何内容,那么为什么要匹配字符串的其余部分呢? 您必须这样做的唯一原因是您可以将整个字符串替换为捕获组的内容。 但是,如果您可以直接访问该组的内容,为什么还要麻烦这样做呢? 这是一个演示(在 Java 中,因为我不知道你使用的是什么语言):
当“查找”如此简单时,为什么要进行“替换”? 可能是因为你的 API 让事情变得更容易; 这就是我们用 Java 来做这件事的原因。 Java 在其 String 类中有几个面向正则表达式的便捷方法:
replaceAll()
、replaceFirst()
、split()
和matches()
(如果正则表达式匹配整个字符串,则返回true
),但不返回find()
。 并且也没有方便的方法来访问捕获组。 我们无法与 Perl 的单行代码的优雅相媲美:...所以我们满足于这样的 hack:
需要明确的是,我并不是说不要使用这些 hack,或者 Evan 的有什么问题回答——没有。 我只是认为我们应该理解为什么我们使用它们,以及当我们这样做时我们会做出什么权衡。
(This is a continuation of the conversation from the comments to Evan's answer.)
Here's what happens when your (corrected) regex is applied: First, the
.+
matches the whole string. Then it backtracks, giving up most of the characters it just matched until it gets to the point where theB=
can match. Then the(.+?)
matches (and captures) everything it sees until the next part, the semicolon, can match. Then the final.+
gobbles up the remaining characters.All you're really interested in is the "B=" and the ";" and whatever's between them, so why match the rest of the string? The only reason you have to do that is so you can replace the whole string with the contents of the capturing group. But why bother doing that if you can access contents of the group directly? Here's a demonstration (in Java, because I can't tell what language you're using):
Why do a 'replace' when a 'find' is so much more straightforward? Probably because your API makes it easier; that's why we do it in Java. Java has several regex-oriented convenience methods in its String class:
replaceAll()
,replaceFirst()
,split()
, andmatches()
(which returnstrue
iff the regex matches the whole string), but notfind()
. And there's no convenience method for accessing capturing groups, either. We can't match the elegance of Perl one-liners like this:...so we content ourselves with hacks like this:
Just to be clear, I'm not saying not to use these hacks, or that there's anything wrong with Evan's answer--there isn't. I just think we should understand why we use them, and what trade-offs we're making when we do.