Como obter uma string entre dois caracteres?

95

Eu tenho uma corda,

String s = "test string (67)";

Eu quero pegar o nº 67, que é a string entre (e).

Alguém pode me dizer como fazer isso?

Roshanck
fonte
1
Existem várias maneiras - você pode iterar os caracteres na seqüência até chegar ao (ou encontrar o índice do primeiro (e )e fazê-lo com substring ou, o que a maioria das pessoas faria, usar uma expressão regular.
Andreas Dolk

Respostas:

103

Provavelmente existe um RegExp muito bom, mas sou novato nessa área, então ...

String s = "test string (67)";

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

System.out.println(s);
MadProgrammer
fonte
4
Sem passar pelas esquisitices da análise regex, acho que essa é a melhor maneira de extrair a string necessária.
verossimilhança
3
regex é de longe mais poderoso e pode aceitar mais casos, mas para simplificar, isso funciona ...
MadProgrammer
2
Sério, por que isso atrairia um voto negativo? Não funciona? Não responde à pergunta das operações?
MadProgrammer
se eu tiver vários valores, como posso usar substring, considere que tenho uma string como essa 'this is an example of <how><i have it>'e preciso encontrar valores entre '<' e '>' isso
Vignesh
@Vignesh Use uma expressão regular
MadProgrammer
75

Uma solução muito útil para esse problema, que não exige que você faça o indexOf, é usar as bibliotecas Apache Commons .

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

Este método permitirá que você manipule até mesmo se houver várias ocorrências da string de fechamento, o que não será fácil procurando pela string de fechamento indexOf.

Você pode baixar essa biblioteca aqui: https://mvnrepository.com/artifact/org.apache.commons/commons-lang3/3.4

Pini Cheyni
fonte
7
Há também substringsBetween(...)se você espera resultados múltiplos, que é o que eu estava procurando. Obrigado
cahen
72

Tente assim

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

A assinatura do método para substring é:

s.substring(int start, int end);
user2656003
fonte
30

Usando uma expressão 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
fonte
2
Eu acho que você deveria fazer esta combinação não gananciosa usando ". *?" em vez de. Caso contrário, se a string for algo como "string de teste (67) e (68), isso retornará" 67) e (68 ".
Projeto Chthonic
19

Java oferece suporte a expressões regulares , mas elas são meio complicadas se você realmente deseja usá-las para extrair correspondências. Acho que a maneira mais fácil de obter a string que você deseja em seu exemplo é apenas usar o suporte de Expressão Regular no método Stringda classe replaceAll:

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

Isso simplesmente exclui tudo, incluindo o primeiro (, e o mesmo para o )e tudo depois disso. Isso deixa apenas o material entre parênteses.

No entanto, o resultado disso ainda é um String. Se você deseja um resultado inteiro, em vez disso, você precisa fazer outra conversão:

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

Em uma única linha, sugiro:

String input = "test string (67)";
input = input.subString(input.indexOf("(")+1, input.lastIndexOf(")"));
System.out.println(input);`
Chuvoso
fonte
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
fonte
7

Você poderia usar StringUtils da biblioteca comum do apache para fazer isso.

import org.apache.commons.lang3.StringUtils;
...
String s = "test string (67)";
s = StringUtils.substringBetween(s, "(", ")");
....
ChaitanyaBhatt
fonte
7
String result = s.substring(s.indexOf("(") + 1, s.indexOf(")"));
techlearner
fonte
1
Formate seu código recuando 4 espaços. Além disso, eu preencheria um pouco sua resposta explicando o que seu código faz para aqueles que não sabem ao certo o que .substringe .indexOf` faz.
Bugs
6

String de teste test string (67)da qual você precisa obter a String que está aninhada entre duas Strings.

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

Listadas algumas maneiras possíveis : Solução genérica simples:

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

Apache Software Foundation commons.lang3.

StringUtilsA substringBetween()função de classe obtém a String que está aninhada entre duas Strings. Apenas a primeira correspondência é retornada.

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

Substitui a String fornecida pela String que está aninhada entre duas Strings. #395


Padrão com expressões regulares: (\()(.*?)(\)).*

O ponto corresponde (quase) a qualquer personagem .? = .{0,1}, .* = .{0,}, .+ = .{1,}

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

Expressão regular com a classe de utilitário RegexUtilse algumas funções.
      Pattern.DOTALL: Corresponde a qualquer caractere, incluindo um terminador de linha.
      Pattern.MULTILINE: Corresponde a String inteira do início ao ^fim $da sequência 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
fonte
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
fonte
4

Usar 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
fonte
2
Falar de nomes de variáveis ​​pode tornar o método mais amigável.
Zona
3

Outra maneira de fazer usando o método de divisão

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
fonte
3

A maneira menos genérica que encontrei de fazer isso com as classes Regex e 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, ""));
}

Isso pode ajudar em problemas de regex mais complexos, nos quais você deseja obter o texto entre dois conjuntos de caracteres.

Ser estar
fonte
2

A maneira "genérica" ​​de fazer isso é analisar a string desde o início, jogando fora todos os caracteres antes do primeiro colchete, gravando os caracteres depois do primeiro colchete e jogando fora os caracteres depois do segundo colchete.

Tenho certeza de que há uma biblioteca regex ou algo para fazer isso.

Jonathon Ashworth
fonte
Java oferece suporte a expressões regulares. Não há necessidade de uma biblioteca regexp4j;)
Andreas Dolk
2
String s = "test string (67)";

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

A outra solução possível é usar lastIndexOf onde ele irá procurar por caractere ou String de trás para frente.

No meu cenário, eu tinha a seguir String e tive que extrair<<UserName>>

1QAJK-WKJSH_MyApplication_Extract_<<UserName>>.arc

Então, indexOf e StringUtils.substringBetweennão foi útil, pois eles começaram a procurar um personagem desde o início.

Então, eu usei lastIndexOf

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

E isso me dá

<<UserName>>
Ravi
fonte
1

Algo assim:

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
fonte
1

Este é um \D+regex de uso simples e trabalho feito.
Isso seleciona todos os caracteres, exceto dígitos, sem necessidade de complicar

/\D+/
Pascal Tovohery
fonte
1

ele retornará a string original se não houver regex correspondente

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

adicione correspondências ao código

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

---EDITAR---

eu uso https://www.freeformatter.com/java-regex-tester.html#ad-output para testar o regex.

Acontece que é melhor adicionar? após * para menos correspondência. algo assim:

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
fonte