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

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"
}

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

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

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

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.


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

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.


0

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


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\\[([^\\]]+)\\]

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

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/


Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.