使用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[123
和FOO
。
如果我们将正则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