Использование Java для поиска подстроки большей строки с использованием регулярного выражения

140

Если у меня есть такая строка:

FOO[BAR]

Мне нужен общий способ получить строку «BAR» из строки, чтобы независимо от того, какая строка находится в квадратных скобках, она могла бы получить строку.

например

FOO[DOG] = DOG
FOO[CAT] = CAT
digiarnie
источник

Ответы:

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, чтобы избежать этого.
Клет
Используя шаблон выше, как бы вы использовали его для извлечения строки, содержащей строку 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(']'));
zaczap
источник
1
Я бы использовал lastIndexOf(']')вместо этого, который будет обрабатывать вложенные скобки. Кроме того, я считаю, что использование indexOf(char)будет быстрее, чем indexOf(String).
Хосам Али
Пожалуйста. Ваше замечание о производительности также очень актуально, так lastIndexOfкак наверняка будет быстрее найти закрывающую скобку.
Хосам Али
3
что быстрее, indexof substring и т. д. и т. д. или регулярное выражение?
Тоскан
2
см. значение Amit для «извлеченного» ниже: input.indexOf ('[') + 1
gcbound
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]
dansalmo
источник
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]]

Regex не будет работать и вернется BAR[CAT[123и FOO.
Если мы изменим Regex на \[(.*)\]тогда, мы в порядке, но потом, если вы пытаетесь извлечь контент из более сложных вещей, таких как:

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

Ни одно из регулярных выражений не будет работать.

Самый точный Regex для извлечения правильного контента во всех случаях будет намного сложнее, так как для этого потребуется сбалансировать []пары и дать вам их контент.

Более простое решение

Если ваши проблемы становятся сложными, а содержимое []произвольным, вы можете вместо этого сбалансировать пары []и извлечь строку, используя обычный старый код, чем 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»
Мохаммад Джафар Мешхади
1
String input = "FOO[BAR]";
String result = input.substring(input.indexOf("[")+1,input.lastIndexOf("]"));

Это вернет значение между первым '[' и последним ']'

Foo [Bar] => Бар

Foo [Bar [тест]] => Бар [тест]

Примечание: вы должны добавить проверку ошибок, если входная строка не правильно сформирована.

Амит
источник
0

при условии, что никакие другие закрывающие квадратные скобки не допускаются в / FOO \ [([^ \]] *) \] /

Manu
источник
0

Я бы определил, что я хочу максимальное количество не] символов между [и ]. Они должны быть экранированы с помощью обратной косой черты (а в Java их нужно экранировать снова), и определение non-] является классом символов, то есть внутри [и ](т.е. [^\\]]). Результат:

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/

rusllonrails
источник
0
"FOO[DOG]".replaceAll("^.*?\\[|\\].*", "");

Это вернет строку, содержащую только строку в квадратных скобках.

Это удалит всю строку снаружи из квадратных скобок.

Вы можете проверить этот пример кода Java онлайн: http://tpcg.io/wZoFu0

Вы можете проверить это регулярное выражение здесь: https://regex101.com/r/oUAzsS/1

Хорхе Вандер Сантана Уренья
источник