使用Java来使用正则expression式查找较大string的子string

如果我有这样的string:

FOO[BAR] 

我需要一个通用的方式来从string中获取“BAR”string,以便不pipe方括号之间的string是什么string都可以得到string。

例如

 FOO[DOG] = DOG FOO[CAT] = CAT 

你应该可以使用非贪婪的量词,特别是* ?. 你可能会想要以下内容:

 Pattern MY_PATTERN = Pattern.compile("\\[(.*?)\\]"); 

这将给你一个模式,将匹配你的string,并把方括号内的文字放在第一组。 查看Pattern API文档以获取更多信息。

要提取string,可以使用如下所示的内容:

 Matcher m = MY_PATTERN.matcher("FOO[BAR]"); while (m.find()) { String s = m.group(1); // s now contains "BAR" } 

非正则expression式的方式:

 String input = "FOO[BAR]", extracted; extracted = input.substring(input.indexOf("["),input.indexOf("]")); 

或者,稍微更好的性能/内存使用(谢谢Hosam):

 String input = "FOO[BAR]", extracted; extracted = input.substring(input.indexOf('['),input.lastIndexOf(']')); 

这是一个工作的例子:

RegexpExample.java

 package org.regexp.replace; import java.util.ArrayList; import java.util.List; import java.util.regex.Matcher; import java.util.regex.Pattern; public class RegexpExample { public static void main(String[] args) { String string = "var1[value1], var2[value2], var3[value3]"; Pattern pattern = Pattern.compile("(\\[)(.*?)(\\])"); Matcher matcher = pattern.matcher(string); List<String> listMatches = new ArrayList<String>(); while(matcher.find()) { listMatches.add(matcher.group(2)); } for(String s : listMatches) { System.out.println(s); } } } 

它显示:

 value1 value2 value3 
 import java.util.*; import java.util.regex.Matcher; import java.util.regex.Pattern; public static String get_match(String s, String p) { // returns first match of p in s for first group in regular expression Matcher m = Pattern.compile(p).matcher(s); return m.find() ? m.group(1) : ""; } get_match("FOO[BAR]", "\\[(.*?)\\]") // returns "BAR" public static List<String> get_matches(String s, String p) { // returns all matches of p in s for first group in regular expression List<String> matches = new ArrayList<String>(); Matcher m = Pattern.compile(p).matcher(s); while(m.find()) { matches.add(m.group(1)); } return matches; } get_matches("FOO[BAR] FOO[CAT]", "\\[(.*?)\\]")) // returns [BAR, CAT] 

如果你只需要得到[]之间的任何东西,你可以像这样使用\[([^\]]*)\]

 Pattern regex = Pattern.compile("\\[([^\\]]*)\\]"); Matcher m = regex.matcher(str); if (m.find()) { result = m.group(); } 

如果您需要它是表单identifier + [ + content + ]那么只有在标识符是字母数字时才可以限制提取内容:

 [a-zA-Z][azA-Z0-9_]*\s*\[([^\]]*)\] 

这将validation例如Foo [Bar]myDevice_123["input"]等。

主要问题

主要的问题是当你想提取这样的内容:

 FOO[BAR[CAT[123]]+DOG[FOO]] 

正则expression式不会工作,并会返回BAR[CAT[123FOO
如果我们将正则expression式改为\[(.*)\]那么我们就可以,但是如果您尝试从更复杂的东西中提取内容,如:

 FOO[BAR[CAT[123]]+DOG[FOO]] = myOtherFoo[BAR[5]] 

没有正则expression式将工作。

在所有情况下,提取正确内容的最准确的正则expression式会更加复杂,因为它需要平衡[]对,并为它们提供内容。

更简单的解决scheme

如果你的问题变得越来越复杂,并且[]任意的内容,你可以取而代之的平衡[]的对,并使用普通的旧代码比正则expression式提取string:

 int i; int brackets = 0; string c; result = ""; for (i = input.indexOf("["); i < str.length; i++) { c = str.substring(i, i + 1); if (c == '[') { brackets++; } else if (c == ']') { brackets--; if (brackets <= 0) break; } result = result + c; } 

这是比真正的代码更伪代码,我不是一个Java编码器,所以我不知道如果语法是正确的,但它应该很容易进行改进。
这个代码应该有效,并且允许你提取[]的内容,不pipe它是多么的复杂。

我认为你的正则expression式看起来像:

 /FOO\[(.+)\]/ 

假设FOO将保持不变。

所以,把它放在Java中:

 Pattern p = Pattern.compile("FOO\\[(.+)\\]"); Matcher m = p.matcher(inputLine); 
 String input = "FOO[BAR]"; String result = input.substring(input.indexOf("[")+1,input.lastIndexOf("]")); 

这将返回第一个'['和最后']'之间的值

Foo [Bar] => Bar

Foo [Bar [test]] => Bar [test]

注意:如果inputstring格式不正确,应该添加错误检查。

假设在其内不允许有其他方括号,/ FOO \ [([^ \]] *)\] /

我会定义我需要在[]之间有最大数量的非]字符。 这些需要用反斜杠(在Java中,这些需要再次转义)转义,非]的定义是一个字符类,因此在[] (即[^\\]] )内。 结果:

 FOO\\[([^\\]]+)\\] 

像这样的工作,如果你想parsing一些来自mYearInDB.toString()= [2013]的string,它会给2013年

 Matcher n = MY_PATTERN.matcher("FOO[BAR]"+mYearInDB.toString()); while (n.find()) { extracredYear = n.group(1); // s now contains "BAR" } System.out.println("Extrated output is : "+extracredYear); 

这个正则expression式适用于我:

 form\[([^']*?)\] 

例:

 form[company_details][0][name] form[company_details][0][common_names][1][title] 

输出:

 Match 1 1. company_details Match 2 1. company_details 

http://rubular.com/上testing