Làm thế nào để lấy một chuỗi giữa hai ký tự?


93

Tôi có một chuỗi,

String s = "test string (67)";

Tôi muốn lấy số 67 là chuỗi giữa (và).

Bất cứ ai có thể xin vui lòng cho tôi biết làm thế nào để làm điều này?


1
Có một số cách - bạn có thể lặp lại các ký tự trong chuỗi cho đến khi bạn đạt được (hoặc tìm chỉ số những người đầu tiên ()và làm điều đó với substring hay, những gì hầu hết mọi người sẽ làm gì, sử dụng một biểu thức chính quy.
Andreas Dolk,

Câu trả lời:


102

Có lẽ có một RegExp thực sự gọn gàng, nhưng tôi không thích lĩnh vực đó, vì vậy thay vào đó ...

String s = "test string (67)";

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

System.out.println(s);

4
Tôi nghĩ đây là cách tốt nhất để trích xuất chuỗi cần thiết mà không cần phải trải qua những điều kỳ lạ của việc phân tích cú pháp regex.
verisimilitude

3
regex là đến nay mạnh hơn và có thể mất trong các trường hợp hơn, nhưng vì đơn giản, các công trình này ...
MadProgrammer

2
Nghiêm túc mà nói, tại sao điều này lại thu hút một cuộc bỏ phiếu giảm? Nó không hoạt động? Nó không trả lời câu hỏi hoạt động?
MadProgrammer

nếu tôi có nhiều giá trị thì làm sao tôi có thể sử dụng substring xem xét tôi có chuỗi như thế này 'this is an example of <how><i have it>'và tôi cần phải tìm các giá trị giữa '<' và '>' này
Vignesh

@Vignesh Sử dụng một biểu thức chính quy
MadProgrammer

74

Một giải pháp rất hữu ích cho vấn đề này mà không yêu cầu bạn thực hiện indexOf là sử dụng các thư viện Apache Commons .

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

Phương pháp này sẽ cho phép bạn thậm chí xử lý ngay cả khi có nhiều lần xuất hiện của chuỗi đóng, điều này sẽ không dễ dàng bằng cách tìm kiếm chuỗi đóng indexOf.

Bạn có thể tải xuống thư viện này từ đây: https://mvnrepository.com/artifact/org.apache.commons/commons-lang3/3.4


7
Cũng có substringsBetween(...)nếu bạn mong đợi nhiều kết quả, đó là những gì tôi đang tìm kiếm. Cảm ơn
cahen


72

Hãy thử nó như thế này

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

Chữ ký của phương thức cho chuỗi con là:

s.substring(int start, int end);

30

Bằng cách sử dụng biểu thức chính quy:

 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
Tôi nghĩ bạn nên biến nó thành một kết hợp không tham lam bằng cách sử dụng ". *?" thay thế. Nếu không, nếu chuỗi được soemthing như "chuỗi thử nghiệm (67) và (68), điều này sẽ trở về "67) và (68".
Chthonic Dự án

18

Java hỗ trợ Biểu thức chính quy , nhưng chúng hơi cồng kềnh nếu bạn thực sự muốn sử dụng chúng để trích xuất các kết quả phù hợp. Tôi nghĩ rằng cách dễ nhất để có được chuỗi bạn muốn trong ví dụ của mình là chỉ sử dụng hỗ trợ Biểu thức chính quy trong phương thức Stringcủa lớp replaceAll:

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

Thao tác này chỉ đơn giản là xóa mọi thứ từ đầu đến và bao gồm cả thứ đầu tiên (, cũng như những )thứ tương tự cho và mọi thứ sau đó. Điều này chỉ để lại nội dung giữa dấu ngoặc đơn.

Tuy nhiên, kết quả của việc này vẫn là a String. Nếu bạn muốn có kết quả số nguyên thì bạn cần thực hiện một chuyển đổi khác:

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

10

Trong một dòng đơn, tôi đề nghị:

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

Bạn có thể sử dụng StringUtils của thư viện chung apache để thực hiện việc này.

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
Vui lòng định dạng mã của bạn bằng cách thụt lề 4 dấu cách. Ngoài ra, tôi sẽ giải thích câu trả lời của bạn một chút bằng cách giải thích mã của bạn có tác dụng gì đối với những người truy cập không chắc chắn về những gì .substringvà .indexOf` làm.
Lỗi

6

Kiểm tra Chuỗi test string (67)mà từ đó bạn cần lấy Chuỗi được lồng vào giữa hai Chuỗi.

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

Liệt kê một số cách khả thi : Giải pháp Chung Đơn giản:

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

Tổ chức phần mềm Apache commons.lang3.

StringUtilssubstringBetween()hàm lớp nhận Chuỗi được lồng vào giữa hai Chuỗi. Chỉ có trận đấu đầu tiên được trả lại.

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

Thay thế Chuỗi đã cho, bằng Chuỗi được lồng vào giữa hai Chuỗi. #395


Mẫu có Biểu thức chính quy: (\()(.*?)(\)).*

Dấu chấm phù hợp (Hầu như) bất kỳ ký tự nào .? = .{0,1}, .* = .{0,}, .+ = .{1,}

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

Biểu thức chính quy với lớp tiện ích RegexUtilsvà một số chức năng.
      Pattern.DOTALL: Khớp với bất kỳ ký tự nào, kể cả ký tự kết thúc dòng.
      Pattern.MULTILINE: Khớp toàn bộ Chuỗi từ đầu ^đến cuối $chuỗi đầu vào.

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 rất hữu ích
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 "" ;
}

Sử dụng :

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

4

Sử dụng 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
Nói tên biến có thể làm cho phương thức thân thiện hơn.
Zon

3

Một cách khác để thực hiện bằng cách sử dụng phương pháp tách

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

Cách ít chung chung nhất mà tôi tìm thấy để làm điều này với các lớp Regex và 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, ""));
}

Điều này có thể hữu ích cho các sự cố regex phức tạp hơn mà bạn muốn lấy văn bản giữa hai bộ ký tự.


2

Cách làm "chung chung" là phân tích cú pháp chuỗi ngay từ đầu, loại bỏ tất cả các ký tự trước dấu ngoặc đơn đầu tiên, ghi lại các ký tự sau dấu ngoặc thứ nhất và loại bỏ các ký tự sau dấu ngoặc thứ hai.

Tôi chắc chắn rằng có một thư viện regex hoặc một cái gì đó để làm điều đó.


Java hỗ trợ các biểu thức chính quy. Không cần thiết cho một thư viện regexp4j;)
Andreas Dolk

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

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

2

Giải pháp khả thi khác là sử dụng lastIndexOf nơi nó sẽ tìm kiếm ký tự hoặc Chuỗi từ phía sau.

Trong kịch bản của tôi, tôi đã theo dõi Stringvà tôi phải trích xuất<<UserName>>

1QAJK-WKJSH_MyApplication_Extract_<<UserName>>.arc

Vì vậy, indexOfStringUtils.substringBetweenkhông hữu ích khi họ bắt đầu tìm kiếm nhân vật ngay từ đầu.

Vì vậy, tôi đã sử dụng lastIndexOf

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

Và, nó mang lại cho tôi

<<UserName>>

1

Một cái gì đó như thế này:

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

Đây là một \D+regex sử dụng đơn giản và công việc đã hoàn thành.
Điều này chọn tất cả các ký tự ngoại trừ các chữ số, không cần phải phức tạp

/\D+/

1

nó sẽ trả về chuỗi ban đầu nếu không có regex khớp

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

thêm các kết quả phù hợp vào mã

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

---BIÊN TẬP---

tôi sử dụng https://www.freeformatter.com/java-regex-tester.html#ad-output để kiểm tra regex.

hóa ra nó tốt hơn để thêm? sau * để ít khớp hơn. một cái gì đó như thế này:

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
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.