¿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?

Roshanck
fuente
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);
Programador loco
fuente
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

Pini Cheyni
fuente
7
También hay substringsBetween(...)si esperas múltiples resultados, que es lo que estaba buscando. Gracias
cahen
Enlace con más ejemplos
commons.apache.org/proper/commons-lang/javadocs/api-2.6/org/…
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);
usuario2656003
fuente
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)); 
Grisha Weintraub
fuente
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
DaoWen
fuente
10

En una sola línea, sugiero:

String input = "test string (67)";
input = input.subString(input.indexOf("(")+1, input.lastIndexOf(")"));
System.out.println(input);`
Lluvioso
fuente
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
Piotr Chojnacki
fuente
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, "(", ")");
....
ChaitanyaBhatt
fuente
7
String result = s.substring(s.indexOf("(") + 1, s.indexOf(")"));
técnico
fuente
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;
}
Yash
fuente
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"
SR
fuente
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);

    }

}
Kumar Vivek Mitra
fuente
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]);
}
Jayy
fuente
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.

Ser - estar
fuente
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.

Jonathon Ashworth
fuente
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(")")));
Vinod
fuente
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>>
Ravi
fuente
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;
}
Ahmad AlMughrabi
fuente
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+/
Pascal Tovohery
fuente
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
bigiCrab
fuente