Jak uzyskać ciąg między dwoma znakami?


93

Mam sznurek,

String s = "test string (67)";

Chcę uzyskać numer 67, który jest ciągiem między (i).

Czy ktoś może mi powiedzieć, jak to zrobić?


1
Istnieje kilka sposobów - można iteracyjne znaków w ciągu, aż dojdziesz do (lub znaleźć indeks pierwszego (i )i zrobić z podciąg lub, co większość ludzi zrobić, należy użyć wyrażenia regularnego.
Andreas Dolk

Odpowiedzi:


103

Prawdopodobnie istnieje naprawdę fajne RegExp, ale jestem noobem w tej dziedzinie, więc zamiast tego ...

String s = "test string (67)";

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

System.out.println(s);

4
Myślę, że to najlepszy sposób na wyodrębnienie wymaganego ciągu bez przechodzenia przez dziwactwa związane z analizą wyrażeń regularnych.
Verisimilitude

3
regex jest znacznie potężniejszy i może wytrzymać więcej przypadków, ale dla uproszczenia działa ...
MadProgrammer

2
Poważnie, dlaczego miałoby to przyciągnąć głos negatywny? Czy to nie działa? Czy to nie odpowiada na pytanie dotyczące operacji?
MadProgrammer

jeśli mam wiele wartości, jak mogę użyć podłańcucha, rozważ, że mam ciąg taki 'this is an example of <how><i have it>'i muszę znaleźć wartości między '<' a '>' to
Vignesh

@Vignesh Użyj wyrażenia regularnego
MadProgrammer

74

Bardzo przydatnym rozwiązaniem tego problemu, które nie wymaga od ciebie wykonania indexOf, jest użycie bibliotek Apache Commons .

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

Ta metoda pozwoli ci nawet obsłużyć, nawet jeśli istnieje wiele wystąpień ciągu zamykającego, co nie będzie łatwe, szukając ciągu indexOf zamykającego.

Możesz pobrać tę bibliotekę stąd: https://mvnrepository.com/artifact/org.apache.commons/commons-lang3/3.4


7
Jest też, substringsBetween(...)jeśli spodziewasz się wielu wyników, czego szukałem. Dzięki
cahen


72

Spróbuj w ten sposób

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

Podpis metody dla podciągu to:

s.substring(int start, int end);

30

Używając wyrażenia regularnego:

 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
Myślę, że powinieneś uczynić to nie chciwym dopasowaniem, używając ". *?" zamiast. W przeciwnym razie, jeśli ciąg ma postać „ciąg testowy (67) i (68)”, to zwróci „67) i (68”.
Projekt Chthonic

18

Java obsługuje wyrażenia regularne , ale są one dość kłopotliwe, jeśli faktycznie chcesz ich używać do wyodrębniania dopasowań. Myślę, że najłatwiejszym sposobem uzyskania ciągu, który chcesz w swoim przykładzie, jest użycie obsługi wyrażeń regularnych w metodzie Stringklasy replaceAll:

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

To po prostu usuwa wszystko, aż do pierwszego (i to samo dla )wszystkich następnych. To po prostu pozostawia zawartość między nawiasami.

Jednak wynik tego nadal jest String. Jeśli zamiast tego chcesz otrzymać wynik w postaci liczby całkowitej, musisz wykonać kolejną konwersję:

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

10

W jednej linii proponuję:

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

Aby to zrobić, możesz użyć StringUtils biblioteki wspólnej 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(")"));

1
Sformatuj kod, wciskając 4 spacje. Chciałbym również trochę .substringuściślić twoją odpowiedź, wyjaśniając, co robi twój kod dla tych odwiedzających, którzy nie są pewni, co i .indexOf` robi.
Błędy

6

Ciąg testowy, test string (67)z którego musisz pobrać ciąg, który jest zagnieżdżony między dwoma ciągami.

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

Wymieniono kilka możliwych sposobów : Proste rozwiązanie ogólne:

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

Fundacja oprogramowania Apache commons.lang3.

StringUtilsclass substringBetween()funkcja pobiera ciąg, który jest zagnieżdżony między dwoma ciągami. Zwracane jest tylko pierwsze dopasowanie.

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

Zastępuje dany ciąg String, który jest zagnieżdżony między dwoma ciągami. #395


Wzorzec z wyrażeniami regularnymi: (\()(.*?)(\)).*

The Dot zestawienia (prawie) dowolny znak .? = .{0,1}, .* = .{0,}, .+ = .{1,}

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

Wyrażenie regularne z klasą narzędziową RegexUtilsi niektórymi funkcjami.
      Pattern.DOTALL: Dopasowuje dowolny znak, w tym terminator linii.
      Pattern.MULTILINE: Dopasowuje cały ciąg od początku ^do końca $sekwencji wejściowej.

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 jest bardzo przydatne
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 "" ;
}

Stosowanie :

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

4

Posługiwać się 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
Wymawianie nazw zmiennych może uczynić metodę bardziej przyjazną.
Zon

3

Inny sposób na użycie metody split

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

Najmniej ogólny sposób, w jaki udało mi się to zrobić z klasami Regex i 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, ""));
}

Może to pomóc w przypadku bardziej złożonych problemów z wyrażeniami regularnymi, w których chcesz umieścić tekst między dwoma zestawami znaków.


2

„Ogólny” sposób polega na przeanalizowaniu ciągu od początku, odrzuceniu wszystkich znaków przed pierwszym nawiasem, zarejestrowaniu znaków po pierwszym nawiasie i wyrzuceniu znaków po drugim nawiasie.

Jestem pewien, że istnieje biblioteka wyrażeń regularnych lub coś do tego.


Java obsługuje wyrażenia regularne. Nie potrzeba biblioteki regexp4j;)
Andreas Dolk

2
String s = "test string (67)";

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

2

Innym możliwym rozwiązaniem jest użycie miejsca, w lastIndexOfktórym będzie szukał znaku lub ciągu od tyłu.

W moim scenariuszu podążałem za Stringi musiałem wydobyć<<UserName>>

1QAJK-WKJSH_MyApplication_Extract_<<UserName>>.arc

Więc indexOfi StringUtils.substringBetweennie był pomocny, ponieważ zaczęli szukać postaci od początku.

Więc użyłem lastIndexOf

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

I to mi daje

<<UserName>>

1

Coś takiego:

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

To jest prosty \D+regex użycia i praca wykonana.
Spowoduje to wybranie wszystkich znaków z wyjątkiem cyfr, bez konieczności komplikowania

/\D+/

1

Zwróci oryginalny ciąg, jeśli nie pasuje do wyrażenia regularnego

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

dodaj dopasowania do kodu

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

---EDYTOWAĆ---

używam https://www.freeformatter.com/java-regex-tester.html#ad-output do testowania wyrażenia regularnego.

okazuje się, że lepiej dodać? po * dla mniejszego dopasowania. coś takiego:

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
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.