116

I have a string,

String s = "test string (67)";

I want to get the no 67 which is the string between ( and ).

Can anyone please tell me how to do this?

duggu
  • 37,851
  • 12
  • 116
  • 113
Roshanck
  • 2,220
  • 8
  • 41
  • 56
  • 1
    There are several ways - you could iterate the chars in the string until you reach the `(` or find the index of the first `(` and `)` and do it with substring or, what most people would do, use a regular expression. – Andreas Dolk Sep 26 '12 at 05:27

22 Answers22

133

There's probably a really neat RegExp, but I'm noob in that area, so instead...

String s = "test string (67)";

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

System.out.println(s);
MadProgrammer
  • 343,457
  • 22
  • 230
  • 366
  • 4
    Without going through the oddities of regex parsing, I think this is the best way to extract the required string. – verisimilitude Sep 26 '12 at 08:54
  • 3
    regex is by far more powerful and can take in more cases, but for simplicity, this works... – MadProgrammer Sep 26 '12 at 09:19
  • 3
    Seriously, why would this attract a down vote? Does it it not work? Does it not answer the ops question? – MadProgrammer Dec 07 '15 at 19:19
  • if I have multiple values then how can I use substring consider i have string like this `'this is an example of '` and i need to find values between '<' and '>' this – Vignesh Jun 11 '18 at 12:27
  • @Vignesh Use a regular expression – MadProgrammer Jun 11 '18 at 20:10
  • can you give me an example I had tied it but could not get the desired output..How to specify the special characters in regex.@MadProgrammer – Vignesh Jun 12 '18 at 06:33
  • @Vignesh [Regular Expression to find a string included between two characters while EXCLUDING the delimiters](https://stackoverflow.com/questions/1454913/regular-expression-to-find-a-string-included-between-two-characters-while-exclud) – MadProgrammer Jun 12 '18 at 06:34
  • hi @MadProgrammer i have tried to get the value from following code but could not get is `var regex = /<(.*?)\>/g; var str = ","; var match = regex.exec(str); match;` my code is as about only getting `card` i also want `tech` in output – Vignesh Jun 12 '18 at 13:10
  • @MadProgrammer - what about performance? when one has to repeat this for several millions of strings? – MasterJoe Mar 17 '20 at 01:50
  • @MasterJoe2 I couldn't tell you, spinning up a regular expression engine will have some overhead, but then again, you might be able to do that ahead of time and re-use it – MadProgrammer Mar 17 '20 at 05:46
  • This is problematic unless you only ever have those characters where you want the string. ie. with String s = "test string 67:"; where you want the the string between a SPACE and a COLON. There are other spaces, so this won't work. So this is not specifically looking for the string between those two characters. – SupermanKelly Dec 22 '20 at 12:24
  • @SupermanKelly Any solution is going to need to be tweaked for individual needs, for example, I often find that I start with a wide match and then narrow it down, often over a number of requests – MadProgrammer Dec 22 '20 at 22:27
  • @SupermanKelly So, I that very specific case, I'd consider finding the `;` and the find the index of the last "space", so a two step workflow - but if you can make a RegExp that works, I might consider that instead - but you'd need to focus on what you're trying to achieve and find the solution(s) which will work for your specific case – MadProgrammer Dec 22 '20 at 22:35
126

A very useful solution to this issue which doesn't require from you to do the indexOf is using Apache Commons libraries.

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

This method will allow you even handle even if there multiple occurrences of the closing string which wont be easy by looking for indexOf closing string.

You can download this library from here: https://mvnrepository.com/artifact/org.apache.commons/commons-lang3/3.4

Pini Cheyni
  • 5,073
  • 2
  • 40
  • 58
  • 13
    There's also `substringsBetween(...)` if you expect multiple results, which is what I was looking for. Thanks – cahen Apr 17 '19 at 14:58
  • 1
    Link with more example- https://commons.apache.org/proper/commons-lang/javadocs/api-2.6/org/apache/commons/lang/StringUtils.html#substringsBetween(java.lang.String,%20java.lang.String,%20java.lang.String) – Avisek Chakraborty Jan 19 '20 at 09:53
  • Unfortunately, this will not produce all possible combinations, when you have a string like: "a-b-c-d-e". I expect to have: b, c, d. Whereas the actual result is: b, d. In other words, it gives you combinations with mutually excluded separators only. – Vasiliy Vlasov Nov 17 '22 at 15:58
85

Try it like this

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

The method's signature for substring is:

s.substring(int start, int end);
JNYRanger
  • 6,829
  • 12
  • 53
  • 81
user2656003
  • 859
  • 6
  • 2
30

By using regular expression :

 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
  • 7,803
  • 1
  • 25
  • 45
  • 3
    I think you should make this a non-greedy match by using ".*?" instead. Otherwise, if the string is soemthing like "test string (67) and (68), this will return "67) and (68". – Chthonic Project Apr 21 '15 at 22:36
19

Java supports Regular Expressions, but they're kind of cumbersome if you actually want to use them to extract matches. I think the easiest way to get at the string you want in your example is to just use the Regular Expression support in the String class's replaceAll method:

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

This simply deletes everything up-to-and-including the first (, and the same for the ) and everything thereafter. This just leaves the stuff between the parenthesis.

However, the result of this is still a String. If you want an integer result instead then you need to do another conversion:

int n = Integer.parseInt(x);
// n is now the integer 67
DaoWen
  • 32,589
  • 6
  • 74
  • 101
11

In a single line, I suggest:

String input = "test string (67)";
input = input.subString(input.indexOf("(")+1, input.lastIndexOf(")"));
System.out.println(input);`
Dani
  • 3,744
  • 4
  • 27
  • 35
Rainy
  • 111
  • 1
  • 2
8

You could use apache common library's StringUtils to do this.

import org.apache.commons.lang3.StringUtils;
...
String s = "test string (67)";
s = StringUtils.substringBetween(s, "(", ")");
....
ChaitanyaBhatt
  • 1,158
  • 14
  • 11
8

Test String test string (67) from which you need to get the String which is nested in-between two Strings.

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

Listed some possible ways: Simple Generic Solution:

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.

StringUtils class substringBetween() function gets the String that is nested in between two Strings. Only the first match is returned.

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

Replaces the given String, with the String which is nested in between two Strings. #395


Pattern with Regular-Expressions: (\()(.*?)(\)).*

The Dot Matches (Almost) Any Character .? = .{0,1}, .* = .{0,}, .+ = .{1,}

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

Regular-Expression with the utility class RegexUtils and some functions.
      Pattern.DOTALL: Matches any character, including a line terminator.
      Pattern.MULTILINE: Matches entire String from the start^ till end$ of the input sequence.

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
  • 9,250
  • 2
  • 69
  • 74
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
  • 6,837
  • 5
  • 34
  • 65
7
String result = s.substring(s.indexOf("(") + 1, s.indexOf(")"));
Iharob Al Asimi
  • 52,653
  • 6
  • 59
  • 97
techlearner
  • 109
  • 1
  • 4
  • 2
    Please format your code by indenting 4 spaces. Also I would pad out your answer a little by explaining what your code does for those visiting who are unsure what `.substring` and .indexOf` does. – Bugs Mar 02 '17 at 10:25
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 "" ;
}

Usage :

String input = "test string (67)";
String startChar = "(";
String endChar   = ")";
String output = getStringBetweenTwoChars(input, startChar, endChar);
System.out.println(output);
// Output: "67"
S.R
  • 2,819
  • 2
  • 22
  • 49
4

Another way of doing using split method

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
  • 2,368
  • 4
  • 24
  • 35
4

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

    }

}
Horrorgoogle
  • 7,858
  • 11
  • 48
  • 81
Kumar Vivek Mitra
  • 33,294
  • 6
  • 48
  • 75
3

The "generic" way of doing this is to parse the string from the start, throwing away all the characters before the first bracket, recording the characters after the first bracket, and throwing away the characters after the second bracket.

I'm sure there's a regex library or something to do it though.

Jonathon Ashworth
  • 1,182
  • 10
  • 20
3

The least generic way I found to do this with Regex and Pattern / Matcher classes:

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, ""));
}

This may help for more complex regex problems where you want to get the text between two set of characters.

Tobe
  • 31
  • 2
3

The other possible solution is to use lastIndexOf where it will look for character or String from backward.

In my scenario, I had following String and I had to extract <<UserName>>

1QAJK-WKJSH_MyApplication_Extract_<<UserName>>.arc

So, indexOf and StringUtils.substringBetween was not helpful as they start looking for character from beginning.

So, I used lastIndexOf

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

And, it gives me

<<UserName>>
Ravi
  • 30,829
  • 42
  • 119
  • 173
2
String s = "test string (67)";

System.out.println(s.substring(s.indexOf("(")+1,s.indexOf(")")));
Vinod
  • 1,965
  • 1
  • 9
  • 18
1

Something like this:

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
  • 1,612
  • 17
  • 28
1

it will return original string if no match regex

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

add matches to the code

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

---EDIT---

i use https://www.freeformatter.com/java-regex-tester.html#ad-output to test regex.

turn out it's better to add ? after * for less match. something like this:

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
  • 91
  • 1
  • 4
1

This is a simple use \D+ regex and job done.
This select all chars except digits, no need to complicate

/\D+/
Pascal Tovohery
  • 888
  • 7
  • 19
0
String s = "(69)";
System.out.println(s.substring(s.lastIndexOf('(')+1,s.lastIndexOf(')')));
desertnaut
  • 57,590
  • 26
  • 140
  • 166
nitish kumar
  • 151
  • 1
  • 5
0

Little extension to top (MadProgrammer) answer

 public static String getTextBetween(final String wholeString, final String str1, String str2){
    String s = wholeString.substring(wholeString.indexOf(str1) + str1.length());
    s = s.substring(0, s.indexOf(str2));
    return s;
}
beginner
  • 2,366
  • 4
  • 29
  • 53