Usando Java para localizar substring de uma cadeia maior usando Expressão Regular

140

Se eu tiver uma string como esta:

FOO[BAR]

Eu preciso de uma maneira genérica de obter a string "BAR" da string, para que não importa qual seja a string entre colchetes, ela poderá obter a string.

por exemplo

FOO[DOG] = DOG
FOO[CAT] = CAT
digiarnie
fonte

Respostas:

253

Você deve poder usar quantificadores não gananciosos, especificamente * ?. Você provavelmente vai querer o seguinte:

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

Isso fornecerá um padrão que corresponderá à sua string e colocará o texto entre colchetes no primeiro grupo. Consulte a documentação da API de padrões para obter mais informações.

Para extrair a string, você pode usar algo como o seguinte:

Matcher m = MY_PATTERN.matcher("FOO[BAR]");
while (m.find()) {
    String s = m.group(1);
    // s now contains "BAR"
}
Bryan Kyle
fonte
16
Vale ressaltar que, se houver uma nova linha entre colchetes, isso falhará e você deverá usar o sinalizador Pattern.DOTALL para evitar isso.
Cletus
Usando o padrão acima, como você usaria isso para extrair a string que contém a string BAR? Estou olhando a API Pattern e a API Matcher, mas ainda não sei como obter a própria string.
Digiarnie 01/03/09
@cletus: Boa chamada! @ Digiarnie: Adicionei uma revisão à resposta que contém alguns códigos para obter a partida.
22710 Bryan Kyle
30

da maneira não regex:

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

alternativamente, para um desempenho / uso de memória um pouco melhor (graças ao Hosam):

String input = "FOO[BAR]", extracted;
extracted = input.substring(input.indexOf('['),input.lastIndexOf(']'));
zaczap
fonte
1
Em lastIndexOf(']')vez disso, eu usaria , que manipularia colchetes aninhados. Além disso, acredito que usar o indexOf(char)seria mais rápido que indexOf(String).
Hosam Aly 02/03/09
De nada. Sua observação sobre desempenho também é muito relevante, pois lastIndexOfcertamente será mais rápido encontrar o colchete.
276 Hosam Aly
3
o que é mais rápido, indexof substring etc etc ou regexp?
Toskan
2
veja o valor de Amit para "extraído" abaixo: input.indexOf ('[') + 1
gcbound
28

Este é um exemplo de trabalho:

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);
        }
    }
}

Exibe:

value1
value2
value3
Djahid Bekka
fonte
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
fonte
5

Se você simplesmente precisar obter o que estiver entre [], poderá usar o \[([^\]]*)\]seguinte:

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

Se você precisar que ele esteja no formato identifier + [ + content + ], poderá limitar a extração do conteúdo apenas quando o identificador for um alfanumérico:

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

Isso irá validar coisas como Foo [Bar], ou myDevice_123["input"]por exemplo.

Problema principal

O principal problema é quando você deseja extrair o conteúdo de algo assim:

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

O Regex não funcionará e retornará BAR[CAT[123e FOO.
Se alterarmos o Regex para, \[(.*)\]então estamos bem, mas, se você estiver tentando extrair o conteúdo de coisas mais complexas, como:

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

Nenhum dos Regexes funcionará.

O Regex mais preciso para extrair o conteúdo adequado em todos os casos seria muito mais complexo, pois seria necessário equilibrar []pares e fornecer a eles o conteúdo.

Uma solução mais simples

Se seus problemas estão ficando complexos e o conteúdo do []arbitrário, você pode equilibrar os pares de []e extrair a string usando o código antigo simples e rathe do que um 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;
}   

Isso é mais pseudo-código do que código real, não sou um codificador Java, portanto não sei se a sintaxe está correta, mas deve ser fácil o suficiente para melhorar.
O que importa é que esse código funcione e permita que você extraia o conteúdo do [], por mais complexo que seja.

Renaud Bompuis
fonte
2

Eu acho que sua expressão regular ficaria assim:

/FOO\[(.+)\]/

Supondo que o FOO seja constante.

Então, para colocar isso em Java:

Pattern p = Pattern.compile("FOO\\[(.+)\\]");
Matcher m = p.matcher(inputLine);
Kevin Lacquement
fonte
FOO [BAR] FOO [BAZ] -> com o seu regex retornará: "BAR] FOO [BAZ"
Mohammad Jafar Mashhadi
1
String input = "FOO[BAR]";
String result = input.substring(input.indexOf("[")+1,input.lastIndexOf("]"));

Isso retornará o valor entre o primeiro '[' e o último ']'

Foo [Bar] => Barra

Foo [Barra [teste]] => Barra [teste]

Nota: Você deve adicionar uma verificação de erro se a sequência de entrada não estiver bem formada.

amit
fonte
0

assumindo que nenhum outro colchete de fechamento seja permitido dentro, / FOO \ [([^ \]] *) \] /

Manu
fonte
0

Eu definiria que quero um número máximo de caracteres não-] entre [e ]. Eles precisam ser escapados com barras invertidas (e em Java, eles precisam ser escapados novamente), e a definição de não] é uma classe de caractere, portanto, interna [e ](ie [^\\]]). O resultado:

FOO\\[([^\\]]+)\\]
Fabian Steeg
fonte
0

Assim funciona, se você deseja analisar alguma string que é proveniente de mYearInDB.toString () = [2013], ela dará 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);

fonte
0

Este regexp funciona para mim:

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

exemplo:

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

resultado:

Match 1
1.  company_details
Match 2
1.  company_details

Testado em http://rubular.com/

rusllonrails
fonte
0
"FOO[DOG]".replaceAll("^.*?\\[|\\].*", "");

Isso retornará uma string, levando apenas a string entre colchetes.

Isso remove toda a corda do lado de fora dos colchetes.

Você pode testar este código de amostra java on-line: http://tpcg.io/wZoFu0

Você pode testar esse regex aqui: https://regex101.com/r/oUAzsS/1

Jorge Wander Santana Ureña
fonte