Comment obtenir une chaîne entre deux caractères?

93

J'ai une ficelle,

String s = "test string (67)";

Je veux obtenir le no 67 qui est la chaîne entre (et).

Quelqu'un peut-il me dire comment faire cela?

Roshanck
la source
1
Il y a plusieurs façons - vous pouvez itérer les caractères dans la chaîne jusqu'à ce que vous atteignez le (ou trouver l'indice de la première (et )et le faire avec ou sous - chaîne, ce que la plupart des gens, utilisez une expression régulière.
Andreas Dolk

Réponses:

103

Il y a probablement un RegExp vraiment sympa, mais je ne suis pas du tout dans ce domaine, alors à la place ...

String s = "test string (67)";

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

System.out.println(s);
MadProgrammer
la source
4
Sans passer par les bizarreries de l'analyse des regex, je pense que c'est le meilleur moyen d'extraire la chaîne requise.
vérisimilitude du
3
regex est de loin plus puissant et peut prendre dans plus de cas, mais pour plus de simplicité, cela fonctionne ...
MadProgrammer
2
Sérieusement, pourquoi cela attirerait-il un vote négatif? Ça ne marche pas? Cela ne répond-il pas à la question des opérations?
MadProgrammer
si j'ai plusieurs valeurs, comment puis-je utiliser une sous-chaîne, considérer que j'ai une chaîne comme celle-ci 'this is an example of <how><i have it>'et que j'ai besoin de trouver des valeurs entre '<' et '>' this
Vignesh
@Vignesh Utiliser une expression régulière
MadProgrammer
74

Une solution très utile à ce problème qui ne vous oblige pas à faire l'indexOf utilise les bibliothèques Apache Commons .

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

Cette méthode vous permettra même de gérer même s'il existe plusieurs occurrences de la chaîne de fermeture, ce qui ne sera pas facile en recherchant la chaîne de fermeture indexOf.

Vous pouvez télécharger cette bibliothèque depuis ici: https://mvnrepository.com/artifact/org.apache.commons/commons-lang3/3.4

Pini Cheyni
la source
7
Il y a aussi substringsBetween(...)si vous attendez plusieurs résultats, c'est ce que je recherchais. Merci
cahen
Lien avec plus exemple- commons.apache.org/proper/commons-lang/javadocs/api-2.6/org/...
Avisek Chakraborty
72

Essayez-le comme ça

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

La signature de la méthode pour la sous-chaîne est:

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

En utilisant une expression régulière:

 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
la source
2
Je pense que vous devriez en faire une correspondance non gourmande en utilisant ". *?" au lieu. Sinon, si la chaîne est quelque chose comme "test string (67) et (68), cela renverra" 67) et (68 ".
Chthonic Project
18

Java prend en charge les expressions régulières , mais elles sont plutôt lourdes si vous voulez réellement les utiliser pour extraire des correspondances. Je pense que le moyen le plus simple d'obtenir la chaîne souhaitée dans votre exemple consiste simplement à utiliser le support des expressions régulières dans la méthode de la Stringclasse replaceAll:

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

Cela supprime simplement tout, y compris le premier (, et de même pour le )et tout par la suite. Cela laisse juste les choses entre les parenthèses.

Cependant, le résultat de ceci est toujours un String. Si vous voulez un résultat entier à la place, vous devez effectuer une autre conversion:

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

En une seule ligne, je propose:

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

Vous pouvez utiliser StringUtils de la bibliothèque commune apache pour ce faire.

import org.apache.commons.lang3.StringUtils;
...
String s = "test string (67)";
s = StringUtils.substringBetween(s, "(", ")");
....
ChaitanyaBhatt
la source
7
String result = s.substring(s.indexOf("(") + 1, s.indexOf(")"));
technicien
la source
1
Veuillez formater votre code en indentant 4 espaces. Aussi, je voudrais compléter votre réponse un peu en expliquant ce que votre code fait pour ceux qui ne savent pas ce que fait .substringet .indexOf`.
Bugs
6

Chaîne test string (67)de test à partir de laquelle vous devez obtenir la chaîne imbriquée entre deux chaînes.

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

Énuméré quelques moyens possibles : Solution générique 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 ));

Fondation Apache Software commons.lang3.

StringUtilsLa substringBetween()fonction de classe obtient la chaîne qui est imbriquée entre deux chaînes. Seule la première correspondance est renvoyée.

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

Remplace la chaîne donnée par la chaîne imbriquée entre deux chaînes. #395


Modèle avec expressions régulières: (\()(.*?)(\)).*

Le point correspond (presque) à n'importe quel caractère .? = .{0,1}, .* = .{0,}, .+ = .{1,}

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

Expression régulière avec la classe utilitaire RegexUtilset certaines fonctions.
      Pattern.DOTALL: Correspond à n'importe quel caractère, y compris une terminaison de ligne.
      Pattern.MULTILINE: Correspond à la chaîne entière du début ^à la fin $de la séquence d'entrée.

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
la source
StringUtils est très utile
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 "" ;
}

Utilisation:

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

Utilisation 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
la source
2
L'énonciation des noms de variables pourrait rendre la méthode plus conviviale.
Zon
3

Une autre façon de faire en utilisant la méthode fractionnée

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
la source
3

Le moyen le moins générique que j'ai trouvé pour le faire avec les classes Regex et 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, ""));
}

Cela peut aider pour des problèmes de regex plus complexes où vous souhaitez obtenir le texte entre deux jeux de caractères.

Être
la source
2

La manière "générique" de faire ceci est d'analyser la chaîne depuis le début, de jeter tous les caractères avant le premier crochet, d'enregistrer les caractères après le premier crochet et de jeter les caractères après le deuxième crochet.

Je suis sûr qu'il existe une bibliothèque de regex ou quelque chose pour le faire.

Jonathon Ashworth
la source
Java prend en charge les expressions régulières. Pas besoin d'une bibliothèque regexp4j;)
Andreas Dolk
2
String s = "test string (67)";

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

L'autre solution possible est d'utiliser lastIndexOf où il recherchera un caractère ou une chaîne à partir de l'arrière.

Dans mon scénario, j'ai suivi Stringet j'ai dû extraire<<UserName>>

1QAJK-WKJSH_MyApplication_Extract_<<UserName>>.arc

Donc, indexOfet cela StringUtils.substringBetweenn'a pas été utile car ils commencent à chercher du personnage depuis le début.

Alors, j'ai utilisé lastIndexOf

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

Et ça me donne

<<UserName>>
Ravi
la source
1

Quelque chose comme ça:

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
la source
1

Ceci est une \D+expression régulière d' utilisation simple et un travail fait.
Cela sélectionne tous les caractères sauf les chiffres, pas besoin de compliquer

/\D+/
Pascal Tovohery
la source
1

il retournera la chaîne d'origine si aucune expression régulière ne correspond

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

ajouter des correspondances au code

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

---ÉDITER---

j'utilise https://www.freeformatter.com/java-regex-tester.html#ad-output pour tester regex.

s'avère qu'il vaut mieux ajouter? après * pour moins de correspondance. quelque chose comme ça:

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
la source