Usando Java para encontrar la subcadena de una cadena más grande usando Expresión regular

140

Si tengo una cadena como esta:

FOO[BAR]

Necesito una forma genérica de sacar la cadena "BAR" de la cadena para que, sin importar qué cadena esté entre corchetes, pueda obtener la cadena.

p.ej

FOO[DOG] = DOG
FOO[CAT] = CAT
digiarnie
fuente

Respuestas:

253

Debería poder utilizar cuantificadores no codiciosos, específicamente * ?. Probablemente quieras lo siguiente:

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

Esto le dará un patrón que coincidirá con su cadena y colocará el texto entre corchetes en el primer grupo. Eche un vistazo a la documentación de Pattern API para obtener más información.

Para extraer la cadena, puede usar algo como lo siguiente:

Matcher m = MY_PATTERN.matcher("FOO[BAR]");
while (m.find()) {
    String s = m.group(1);
    // s now contains "BAR"
}
Bryan Kyle
fuente
16
Vale la pena mencionar que si hay una nueva línea entre los corchetes, esto fallará y debe usar el indicador Pattern.DOTALL para evitarlo.
cletus 01 de
Usando el patrón anterior, ¿cómo usaría eso para extraer la cadena que contiene la barra BAR? Estoy mirando la API de patrones y la API de Matcher, pero todavía no estoy seguro de cómo obtener la cadena en sí.
digiarnie 01 de
@cletus: ¡Buena llamada! @digiarnie: He agregado una revisión a la respuesta que contiene un código de hombre de paja para obtener la coincidencia.
Bryan Kyle
30

la forma no regex:

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

alternativamente, para un rendimiento ligeramente mejor / uso de memoria (gracias Hosam):

String input = "FOO[BAR]", extracted;
extracted = input.substring(input.indexOf('['),input.lastIndexOf(']'));
zaczap
fuente
1
En su lastIndexOf(']')lugar, usaría , que manejaría paréntesis anidados. Además, creo que usar el indexOf(char)sería más rápido que indexOf(String).
Hosam Aly
De nada. Su nota sobre el rendimiento también es muy relevante, ya lastIndexOfque sin duda será más rápido encontrar el corchete de cierre.
Hosam Aly
3
¿Qué es más rápido, indexof substring, etc., etc. o regexp?
Toskan
2
vea el valor de Amit para "extraído" a continuación: input.indexOf ('[') + 1
gcbound
28

Este es un ejemplo de trabajo:

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

Muestra :

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

Si simplemente necesita obtener lo que sea que esté en medio [], puede usarlo \[([^\]]*)\]así:

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

Si necesita que tenga la forma identifier + [ + content + ], puede limitar la extracción del contenido solo cuando el identificador sea alfanumérico:

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

Esto validará cosas como Foo [Bar], myDevice_123["input"]por ejemplo.

Tema principal

El principal problema es cuando quieres extraer el contenido de algo como esto:

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

El Regex no funcionará y volverá BAR[CAT[123y FOO.
Si cambiamos la expresión regular a, \[(.*)\]entonces estamos bien, pero si estás tratando de extraer el contenido de cosas más complejas como:

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

Ninguna de las expresiones regulares funcionará.

El Regex más preciso para extraer el contenido adecuado en todos los casos sería mucho más complejo, ya que necesitaría equilibrar []pares y proporcionarle el contenido.

Una solución más simple

Si sus problemas se vuelven complejos y el contenido de lo []arbitrario, en su lugar, podría equilibrar los pares []y extraer la cadena usando rathe de código simple que un 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;
}   

Esto es más pseudocódigo que código real, no soy un codificador de Java, así que no sé si la sintaxis es correcta, pero debería ser lo suficientemente fácil de mejorar.
Lo que cuenta es que este código debería funcionar y permitirle extraer el contenido del [], por complejo que sea.

Renaud Bompuis
fuente
2

Creo que tu expresión regular se vería así:

/FOO\[(.+)\]/

Asumiendo que FOO va a ser constante.

Entonces, para poner esto en Java:

Pattern p = Pattern.compile("FOO\\[(.+)\\]");
Matcher m = p.matcher(inputLine);
Kevin Lacquement
fuente
FOO [BAR] FOO [BAZ] -> con tu expresión regular regresará: "BAR] FOO [BAZ"
Mohammad Jafar Mashhadi
1
String input = "FOO[BAR]";
String result = input.substring(input.indexOf("[")+1,input.lastIndexOf("]"));

Esto devolverá el valor entre el primer '[' y el último ']'

Foo [Bar] => Bar

Foo [Bar [prueba]] => Bar [prueba]

Nota: Debe agregar la comprobación de errores si la cadena de entrada no está bien formada.

amit
fuente
0

suponiendo que no se permita ningún otro corchete de cierre dentro, / FOO \ [([^ \]] *) \] /

Manu
fuente
0

Definiría que quiero un número máximo de caracteres que no sean] entre [y ]. Estos deben escaparse con barras diagonales invertidas (y en Java, deben escaparse nuevamente), y la definición de no- es una clase de caracteres, por lo tanto, dentro [y ](es decir [^\\]]). El resultado:

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

Así funciona si desea analizar alguna cadena que proviene de mYearInDB.toString () = [2013] le 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);

fuente
0

Esta expresión regular funciona para mí:

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

ejemplo:

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

salida:

Match 1
1.  company_details
Match 2
1.  company_details

Probado en http://rubular.com/

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

Esto devolverá una cadena tomando solo la cadena entre corchetes.

Esto elimina todas las cuerdas del exterior de corchetes.

Puede probar este código de muestra de Java en línea: http://tpcg.io/wZoFu0

Puede probar esta expresión regular desde aquí: https://regex101.com/r/oUAzsS/1

Jorge Wander Santana Ureña
fuente