¿Cómo conseguir una cadena entre dos caracteres?


93

Tengo una cuerda

String s = "test string (67)";

Quiero obtener el no 67, que es la cadena entre (y).

¿Alguien puede decirme cómo hacer esto?


1
Hay varias maneras - se podía repetir los caracteres en la cadena hasta llegar a la (o encontrar el índice de la primera (y )y hacerlo con la subcadena o, lo que la mayoría de la gente haría, utilice una expresión regular.
Andreas Dolk

Respuestas:


103

Probablemente haya una expresión regular realmente buena, pero soy un novato en esa área, así que en cambio ...

String s = "test string (67)";

s = s.substring(s.indexOf("(") + 1);
s = s.substring(0, s.indexOf(")"));

System.out.println(s);

4
Sin pasar por las rarezas del análisis de expresiones regulares, creo que esta es la mejor manera de extraer la cadena requerida.
verosimilitud

3
regex es mucho más poderoso y puede tomar en más casos, pero para simplificar, esto funciona ...
MadProgrammer

2
En serio, ¿por qué esto atraería un voto negativo? ¿No funciona? ¿No responde a la pregunta de operaciones?
MadProgrammer

si tengo varios valores, ¿cómo puedo usar la subcadena? Considere que tengo una cadena como esta 'this is an example of <how><i have it>'y necesito encontrar valores entre '<' y '>' esto
Vignesh

@Vignesh Use una expresión regular
MadProgrammer

74

Una solución muy útil a este problema que no requiere que haga el indexOf es usar las bibliotecas de Apache Commons .

 StringUtils.substringBetween(s, "(", ")");

Este método le permitirá incluso manejar incluso si hay múltiples apariciones de la cadena de cierre, lo que no será fácil al buscar indexOf cadena de cierre.

Puede descargar esta biblioteca desde aquí: https://mvnrepository.com/artifact/org.apache.commons/commons-lang3/3.4


7
También hay substringsBetween(...)si esperas múltiples resultados, que es lo que estaba buscando. Gracias
cahen


72

Pruébalo así

String s="test string(67)";
String requiredString = s.substring(s.indexOf("(") + 1, s.indexOf(")"));

La firma del método para la subcadena es:

s.substring(int start, int end);

30

Usando expresión regular:

 String s = "test string (67)";
 Pattern p = Pattern.compile("\\(.*?\\)");
 Matcher m = p.matcher(s);
 if(m.find())
    System.out.println(m.group().subSequence(1, m.group().length()-1)); 

2
Creo que deberías hacer de esta una coincidencia no codiciosa usando ". *?" en lugar. De lo contrario, si la cadena se soemthing como "cadena de prueba (67) y (68), esto devolverá "67) y (68".
Chthonic Proyecto

18

Java admite expresiones regulares , pero son un poco engorrosas si realmente desea usarlas para extraer coincidencias. Creo que la forma más fácil de llegar a la cadena que desea en su ejemplo es simplemente usar el soporte de Expresión regular en el método de la Stringclase replaceAll:

String x = "test string (67)".replaceAll(".*\\(|\\).*", "");
// x is now the String "67"

Esto simplemente elimina todo, incluido el primero (, y lo mismo para el )y todo lo que sigue. Esto solo deja las cosas entre paréntesis.

Sin embargo, el resultado de esto sigue siendo un String. Si desea un resultado entero en su lugar, debe hacer otra conversión:

int n = Integer.parseInt(x);
// n is now the integer 67

10

En una sola línea, sugiero:

String input = "test string (67)";
input = input.subString(input.indexOf("(")+1, input.lastIndexOf(")"));
System.out.println(input);`

7
String s = "test string (67)";

int start = 0; // '(' position in string
int end = 0; // ')' position in string
for(int i = 0; i < s.length(); i++) { 
    if(s.charAt(i) == '(') // Looking for '(' position in string
       start = i;
    else if(s.charAt(i) == ')') // Looking for ')' position in  string
       end = i;
}
String number = s.substring(start+1, end); // you take value between start and end

7

Puede usar StringUtils de la biblioteca común de Apache para hacer esto.

import org.apache.commons.lang3.StringUtils;
...
String s = "test string (67)";
s = StringUtils.substringBetween(s, "(", ")");
....

7
String result = s.substring(s.indexOf("(") + 1, s.indexOf(")"));

1
Formatee su código sangrando 4 espacios. También quisiera rellenar un poco su respuesta explicando qué hace su código para aquellos visitantes que no están seguros de qué hace .substringy .indexOf`.
Bugs

6

Cadena de prueba test string (67)de la que necesita obtener la cadena que está anidada entre dos cadenas.

String str = "test string (67) and (77)", open = "(", close = ")";

Enumeró algunas formas posibles : Solución genérica simple:

String subStr = str.substring(str.indexOf( open ) + 1, str.indexOf( close ));
System.out.format("String[%s] Parsed IntValue[%d]\n", subStr, Integer.parseInt( subStr ));

Fundación de software Apache commons.lang3.

StringUtilsLa substringBetween()función de clase obtiene la cadena que está anidada entre dos cadenas. Solo se devuelve la primera coincidencia.

String substringBetween = StringUtils.substringBetween(subStr, open, close);
System.out.println("Commons Lang3 : "+ substringBetween);

Reemplaza la cadena dada por la cadena que está anidada entre dos cadenas. #395


Patrón con expresiones regulares: (\()(.*?)(\)).*

El punto coincide (casi) con cualquier personaje .? = .{0,1}, .* = .{0,}, .+ = .{1,}

String patternMatch = patternMatch(generateRegex(open, close), str);
System.out.println("Regular expression Value : "+ patternMatch);

Regular-Expression con la clase de utilidad RegexUtilsy algunas funciones.
      Pattern.DOTALL: Coincide con cualquier carácter, incluido un terminador de línea.
      Pattern.MULTILINE: Coincide con la cadena completa desde el principio ^hasta el final $de la secuencia de entrada.

public static String generateRegex(String open, String close) {
    return "(" + RegexUtils.escapeQuotes(open) + ")(.*?)(" + RegexUtils.escapeQuotes(close) + ").*";
}

public static String patternMatch(String regex, CharSequence string) {
    final Pattern pattern  = Pattern.compile(regex, Pattern.DOTALL);
    final Matcher matcher = pattern .matcher(string);

    String returnGroupValue = null;
    if (matcher.find()) { // while() { Pattern.MULTILINE }
        System.out.println("Full match: " + matcher.group(0));
        System.out.format("Character Index [Start:End]«[%d:%d]\n",matcher.start(),matcher.end());
        for (int i = 1; i <= matcher.groupCount(); i++) {
            System.out.println("Group " + i + ": " + matcher.group(i));
            if( i == 2 ) returnGroupValue = matcher.group( 2 );
        }
    }
    return returnGroupValue;
}

StringUtils es muy útil
TuGordoBello

5
public String getStringBetweenTwoChars(String input, String startChar, String endChar) {
    try {
        int start = input.indexOf(startChar);
        if (start != -1) {
            int end = input.indexOf(endChar, start + startChar.length());
            if (end != -1) {
                return input.substring(start + startChar.length(), end);
            }
        }
    } catch (Exception e) {
        e.printStackTrace();
    }
    return input; // return null; || return "" ;
}

Uso:

String input = "test string (67)";
String startChar = "(";
String endChar   = ")";
String output = getStringBetweenTwoChars(input, startChar, endChar);
System.out.println(output);
// Output: "67"

4

Utilizar Pattern and Matcher

public class Chk {

    public static void main(String[] args) {

        String s = "test string (67)";
        ArrayList<String> arL = new ArrayList<String>();
        ArrayList<String> inL = new ArrayList<String>();

        Pattern pat = Pattern.compile("\\(\\w+\\)");
        Matcher mat = pat.matcher(s);

        while (mat.find()) {

            arL.add(mat.group());
            System.out.println(mat.group());

        }

        for (String sx : arL) {

            Pattern p = Pattern.compile("(\\w+)");
            Matcher m = p.matcher(sx);

            while (m.find()) {

                inL.add(m.group());
                System.out.println(m.group());
            }
        }

        System.out.println(inL);

    }

}

2
Hablar nombres de variables podría hacer que el método sea más amigable.
Zon

3

Otra forma de hacerlo usando el método dividido

public static void main(String[] args) {


    String s = "test string (67)";
    String[] ss;
    ss= s.split("\\(");
    ss = ss[1].split("\\)");

    System.out.println(ss[0]);
}

3

La forma menos genérica que encontré para hacer esto con las clases Regex y Pattern / Matcher:

String text = "test string (67)";

String START = "\\(";  // A literal "(" character in regex
String END   = "\\)";  // A literal ")" character in regex

// Captures the word(s) between the above two character(s)
String pattern = START + "(\w+)" + END;

Pattern pattern = Pattern.compile(pattern);
Matcher matcher = pattern.matcher(text);

while(matcher.find()) {
    System.out.println(matcher.group()
        .replace(START, "").replace(END, ""));
}

Esto puede ayudar para problemas de expresiones regulares más complejos en los que desea obtener el texto entre dos conjuntos de caracteres.


2

La forma "genérica" ​​de hacer esto es analizar la cadena desde el principio, desechando todos los caracteres antes del primer corchete, registrando los caracteres después del primer corchete y desechando los caracteres después del segundo corchete.

Estoy seguro de que hay una biblioteca de expresiones regulares o algo para hacerlo.


Java admite expresiones regulares. No se necesita una biblioteca regexp4j;)
Andreas Dolk

2
String s = "test string (67)";

System.out.println(s.substring(s.indexOf("(")+1,s.indexOf(")")));

2

La otra solución posible es usar lastIndexOfdonde buscará el carácter o la Cadena desde atrás.

En mi escenario, tenía seguimiento Stringy tuve que extraer<<UserName>>

1QAJK-WKJSH_MyApplication_Extract_<<UserName>>.arc

Entonces, indexOfy StringUtils.substringBetweenno fue útil ya que comenzaron a buscar el personaje desde el principio.

Entonces, usé lastIndexOf

String str = "1QAJK-WKJSH_MyApplication_Extract_<<UserName>>.arc";
String userName = str.substring(str.lastIndexOf("_") + 1, str.lastIndexOf("."));

Y me da

<<UserName>>

1

Algo como esto:

public static String innerSubString(String txt, char prefix, char suffix) {

    if(txt != null && txt.length() > 1) {

        int start = 0, end = 0;
        char token;
        for(int i = 0; i < txt.length(); i++) {
            token = txt.charAt(i);
            if(token == prefix)
                start = i;
            else if(token == suffix)
                end = i;
        }

        if(start + 1 < end)
            return txt.substring(start+1, end);

    }

    return null;
}

1

Esta es una \D+expresión regular de uso simple y trabajo hecho.
Esto selecciona todos los caracteres excepto los dígitos, no es necesario complicar

/\D+/

1

devolverá la cadena original si no coincide con la expresión regular

var iAm67 = "test string (67)".replaceFirst("test string \\((.*)\\)", "$1");

agregar coincidencias al código

String str = "test string (67)";
String regx = "test string \\((.*)\\)";
if (str.matches(regx)) {
    var iAm67 = str.replaceFirst(regx, "$1");
}

---EDITAR---

yo uso https://www.freeformatter.com/java-regex-tester.html#ad-output para probar regex.

resulta que es mejor agregar? después de * para menos partido. algo como esto:

String str = "test string (67)(69)";
String regx1 = "test string \\((.*)\\).*";
String regx2 = "test string \\((.*?)\\).*";
String ans1 = str.replaceFirst(regx1, "$1");
String ans2 = str.replaceFirst(regx2, "$1");
System.out.println("ans1:"+ans1+"\nans2:"+ans2); 
// ans1:67)(69
// ans2:67
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.