使用Java使用正则表达式查找较大字符串的子字符串


140

如果我有这样的字符串:

FOO[BAR]

我需要一种从字符串中获取“ BAR”字符串的通用方法,以便无论方括号之间是什么字符串,都可以获取该字符串。

例如

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

Answers:


253

您应该能够使用非贪婪的量词,特别是*?。您可能需要以下条件:

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

这将为您提供一个与您的字符串匹配的模式,并将文本放在第一组的方括号内。请查看Pattern API文档以获取更多信息。

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

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

16
值得一提的是,如果方括号之间有换行符,它将失败,您应该使用Pattern.DOTALL标志来避免这种情况。
cletus

使用上述模式,您将如何使用它来提取包含字符串BAR的字符串?我正在查看Pattern API和Matcher API,但仍不确定如何获取字符串本身。
digiarnie

@cletus:好电话!@digiarnie:我在答案中添加了一个修订,其中包含一些用于获得比赛的稻草人代码。
布赖恩·凯尔

30

非正则表达式方式:

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(']'));

1
我会改用lastIndexOf(']')处理嵌套括号的方法。另外,我相信使用indexOf(char)会比快indexOf(String)
Hosam Aly

别客气。关于性能的注释也非常相关,因为lastIndexOf找到结束括号肯定会更快。
Hosam Aly

3
什么是更快,indexof子字符串等等等或正则表达式?
Toskan

2
请参见下面的“提取”的Amit值:input.indexOf('[')+ 1
gcbound 2013年

28

这是一个工作示例:

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

6
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]

5

如果您只需要获取之间的任何值[],则可以这样使用\[([^\]]*)\]

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

如果您需要它的形式,identifier + [ + content + ]那么仅当标识符为字母数字时,才可以限制提取内容:

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

这将验证之类的东西Foo [Bar],或myDevice_123["input"]为实例。

主要问题

主要问题是当您要提取类似以下内容的内容时:

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

正则表达式将无法正常运行,并且会返回BAR[CAT[123FOO
如果我们将正则表达式更改为,\[(.*)\]则可以,但是,如果您尝试从更复杂的内容中提取内容,例如:

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

这些正则表达式均无法使用。

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

一个更简单的解决方案

如果您的问题变得越来越复杂并且内容的[]任意性[]更大,则可以使用普通的旧代码rathe而不是Regex 来平衡两对并提取字符串:

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程序员,所以我不知道语法是否正确,但是应该很容易进行改进。
重要的是,此代码应该有效,并允许您提取的内容[],无论它多么复杂。


2

我认为您的正则表达式如下所示:

/FOO\[(.+)\]/

假设FOO将保持不变。

因此,将其放入Java中:

Pattern p = Pattern.compile("FOO\\[(.+)\\]");
Matcher m = p.matcher(inputLine);

FOO [BAR] FOO [BAZ]->使用您的正则表达式将返回:“ BAR] FOO [BAZ”
Mohammad Jafar Mashhadi 2013年

1
String input = "FOO[BAR]";
String result = input.substring(input.indexOf("[")+1,input.lastIndexOf("]"));

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

Foo [Bar] => Bar

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

注意:如果输入字符串格式不正确,则应添加错误检查。



0

我定义了在[和之间需要最大数量的非[]字符]。这些需要用反斜杠转义(在Java中,它们需要再次转义),并且non-]的定义是一个字符类,因此位于[and ](即[^\\]])内。结果:

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

0

像这样,如果您要解析来自mYearInDB.toString()= [2013]的字符串,它将得到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);

0

此正则表达式适用于我:

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/上进行了测试


By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.