Как получить строку между двумя символами?

93

У меня есть веревка,

String s = "test string (67)";

Я хочу получить номер 67, который является строкой между (и).

Подскажите, пожалуйста, как это сделать?

Рошанк
источник
1
Есть несколько способов - можно перебирать на символы в строке , пока вы не достигнете (или найти индекс первого (и )и сделать это с подстроки или, что большинство людей будет делать, использовать регулярное выражение.
Андреас Долк

Ответы:

103

Вероятно, есть действительно отличный RegExp, но я новичок в этой области, поэтому вместо этого ...

String s = "test string (67)";

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

System.out.println(s);
Безумный программист
источник
4
Не вдаваясь в странности парсинга регулярных выражений, я считаю, что это лучший способ извлечь требуемую строку.
правдоподобие
3
regex намного мощнее и может принимать больше случаев, но для простоты это работает ...
MadProgrammer
2
Серьезно, почему это привлекло голосование против? Не получается? Не отвечает на вопрос ops?
MadProgrammer
если у меня несколько значений, то как я могу использовать подстроку, учитывая, что у меня есть такая строка, 'this is an example of <how><i have it>'и мне нужно найти значения между '<' и '>' this
Виньеш
@Vignesh Используйте регулярное выражение
MadProgrammer
74

Очень полезным решением этой проблемы, которое не требует от вас выполнения indexOf, является использование библиотек Apache Commons .

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

Этот метод позволит вам даже обрабатывать, даже если есть несколько вхождений закрывающей строки, что не будет легко, если поискать закрывающую строку indexOf.

Вы можете скачать эту библиотеку отсюда: https://mvnrepository.com/artifact/org.apache.commons/commons-lang3/3.4

Пини Чейни
источник
7
Также есть, substringsBetween(...)если вы ожидаете нескольких результатов, это то, что я искал. Спасибо
cahen
Ссылка с дополнительным примером
commons.apache.org/proper/commons-lang/javadocs/api-2.6/org/…
72

Попробуйте вот так

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

Сигнатура метода для подстроки:

s.substring(int start, int end);
user2656003
источник
30

Используя регулярное выражение:

 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
Я думаю, вы должны сделать это сопоставление не жадным, используя ". *?" вместо. В противном случае, если строка выглядит как «тестовая строка (67) и (68), она вернет« 67) и (68 ».
Chthonic Project
18

Java поддерживает регулярные выражения , но они довольно громоздки, если вы действительно хотите использовать их для извлечения совпадений. Я думаю, что самый простой способ получить строку, которую вы хотите в своем примере, - просто использовать поддержку регулярных выражений в методе Stringкласса replaceAll:

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

Это просто удаляет все, включая первое (, и то же самое, )и все, что после него. Это просто оставляет материал между скобками.

Однако в результате все еще остается файл String. Если вместо этого вы хотите получить целочисленный результат, вам нужно выполнить другое преобразование:

int n = Integer.parseInt(x);
// n is now the integer 67
ДаоВэнь
источник
10

Одной строкой предлагаю:

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

Для этого вы можете использовать StringUtils общей библиотеки apache.

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(")"));
techlearner
источник
1
Отформатируйте код, сделав отступ в 4 пробела. Также я хотел бы немного дополнить ваш ответ, объяснив, что делает ваш код для тех, кто не .substringзнает, что делает и .indexOf`.
Ошибки
6

Тестовая строка, test string (67)из которой вам нужно получить строку, вложенную между двумя строками.

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

Перечислил несколько возможных способов : Простое универсальное решение:

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 commons.lang3.

StringUtilssubstringBetween()Функция класса получает строку, вложенную между двумя строками. Возвращается только первое совпадение.

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

Заменяет данную строку на строку, вложенную между двумя строками. #395


Шаблон с регулярными выражениями: (\()(.*?)(\)).*

В Dot матчи (Почти) Любой символ .? = .{0,1}, .* = .{0,}, .+ = .{1,}

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

Регулярное выражение с служебным классом RegexUtilsи некоторыми функциями.
      Pattern.DOTALL: Соответствует любому символу, включая символ конца строки.
      Pattern.MULTILINE: Соответствует всей строке от начала ^до конца $входной последовательности.

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 очень
полезен
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 "" ;
}

Применение :

String input = "test string (67)";
String startChar = "(";
String endChar   = ")";
String output = getStringBetweenTwoChars(input, startChar, endChar);
System.out.println(output);
// Output: "67"
SR
источник
4

Использовать 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
Использование имен переменных может сделать метод более удобным.
Зон
3

Другой способ использования метода разделения

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

Наименее общий способ сделать это с помощью классов Regex и 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, ""));
}

Это может помочь в решении более сложных проблем с регулярным выражением, когда вы хотите поместить текст между двумя наборами символов.

Быть
источник
2

«Общий» способ сделать это - проанализировать строку с самого начала, отбросив все символы перед первой скобкой, записав символы после первой скобки и отбросив символы после второй скобки.

Я уверен, что есть библиотека регулярных выражений или что-то для этого.

Джонатон Эшворт
источник
Java поддерживает регулярные выражения. Нет необходимости в библиотеке regexp4j;)
Андреас Долк
2
String s = "test string (67)";

System.out.println(s.substring(s.indexOf("(")+1,s.indexOf(")")));
Винод
источник
2

Другое возможное решение - использовать то место, lastIndexOfгде он будет искать символ или строку в обратном направлении.

В моем сценарии у меня были подписчики, Stringи мне пришлось извлечь<<UserName>>

1QAJK-WKJSH_MyApplication_Extract_<<UserName>>.arc

Таким образом, indexOfи StringUtils.substringBetweenне полезно , как они начинают искать символ от начала.

Итак, я использовал lastIndexOf

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

И это дает мне

<<UserName>>
Рави
источник
1

Что-то вроде этого:

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

Это простое \D+регулярное выражение, и работа сделана.
Это выберите все символы, кроме цифр, не нужно усложнять

/\D+/
Паскаль Товогери
источник
1

он вернет исходную строку, если регулярное выражение не соответствует

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

добавить совпадения в код

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

---РЕДАКТИРОВАТЬ---

Я использую https://www.freeformatter.com/java-regex-tester.html#ad-output для проверки регулярного выражения.

получается лучше добавить? после * для меньшего совпадения. что-то вроде этого:

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
источник