จะรับสตริงระหว่างสองอักขระได้อย่างไร


93

ฉันมีสตริง

String s = "test string (67)";

ฉันต้องการรับหมายเลข 67 ซึ่งเป็นสตริงระหว่าง (และ)

ใครช่วยบอกฉันหน่อยได้ไหมว่าต้องทำอย่างไร


1
มีหลายวิธี - คุณสามารถย้ำตัวอักษรในสตริงจนกว่าจะถึง(หรือหาดัชนีของครั้งแรก(และ)และทำมันด้วย substring หรือสิ่งที่คนส่วนใหญ่จะทำใช้การแสดงออกปกติ
Andreas Dolk

คำตอบ:


103

อาจจะมี RegExp ที่เรียบร้อยจริงๆ แต่ฉันไม่มีใครอยู่ในพื้นที่นั้นดังนั้นแทน ...

String s = "test string (67)";

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

System.out.println(s);

4
ฉันคิดว่านี่เป็นวิธีที่ดีที่สุดในการแยกสตริงที่ต้องการโดยไม่ต้องผ่านความแปลกประหลาดของการแยกวิเคราะห์ regex
verisimilitude

3
regex นั้นทรงพลังกว่ามากและสามารถใช้งานได้ในหลายกรณี แต่เพื่อความเรียบง่ายสิ่งนี้ใช้ได้ ...
MadProgrammer

2
อย่างจริงจังทำไมสิ่งนี้ถึงดึงดูดการลงคะแนน? มันไม่ทำงาน? ไม่ตอบคำถาม ops?
MadProgrammer

ถ้าฉันมีหลายค่าฉันจะใช้สตริงย่อยได้อย่างไรโดยพิจารณาว่าฉันมีสตริงแบบนี้'this is an example of <how><i have it>'และฉันต้องหาค่าระหว่าง '<' และ '>' สิ่งนี้
Vignesh

@Vignesh ใช้นิพจน์ทั่วไป
MadProgrammer

74

วิธีแก้ปัญหาที่มีประโยชน์มากสำหรับปัญหานี้ซึ่งคุณไม่ต้องการให้ทำ indexOf ใช้ ไลบรารีApache Commons

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

วิธีนี้จะช่วยให้คุณสามารถจัดการได้แม้ว่าจะมีสตริงปิดเกิดขึ้นหลายครั้งซึ่งจะไม่ง่ายเลยโดยการมองหาดัชนีของสตริงปิด

คุณสามารถดาวน์โหลดไลบรารีนี้ได้จากที่นี่: 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/…
Avisek Chakraborty

72

ลองเป็นแบบนี้

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

ลายเซ็นของวิธีการสำหรับสตริงย่อยคือ:

s.substring(int start, int end);

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 รองรับ Regular Expressionsแต่มันค่อนข้างยุ่งยากหากคุณต้องการใช้มันเพื่อแยกการจับคู่ ฉันคิดว่าวิธีที่ง่ายที่สุดในการรับสตริงที่คุณต้องการในตัวอย่างของคุณคือใช้การสนับสนุน Regular Expression ในวิธีการ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(")"));

1
โปรดจัดรูปแบบรหัสของคุณโดยการเยื้อง 4 ช่องว่าง นอกจากนี้ฉันจะอธิบายคำตอบของคุณเล็กน้อยโดยอธิบายว่ารหัสของคุณทำอะไรสำหรับผู้ที่มาเยี่ยมชมที่ไม่แน่ใจว่าอะไร.substringและ. indexOf` ทำอะไร
Bugs

6

Test String test string (67)ซึ่งคุณต้องการรับ String ซึ่งซ้อนอยู่ระหว่างสอง Strings

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

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

Regular-Expression พร้อมคลาสยูทิลิตี้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 มีประโยชน์มาก
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 "" ;
}

การใช้งาน:

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

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
การพูดชื่อตัวแปรสามารถทำให้วิธีการเป็นมิตรมากขึ้น
Zon

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

ซึ่งอาจช่วยแก้ปัญหา regex ที่ซับซ้อนมากขึ้นซึ่งคุณต้องการรับข้อความระหว่างชุดอักขระสองชุด


2

วิธี "ทั่วไป" ในการทำเช่นนี้คือการแยกวิเคราะห์สตริงตั้งแต่เริ่มต้นโดยทิ้งอักขระทั้งหมดก่อนวงเล็บแรกบันทึกอักขระหลังวงเล็บแรกและทิ้งอักขระหลังวงเล็บที่สอง

ฉันแน่ใจว่ามีไลบรารี regex หรืออะไรที่ต้องทำ


Java รองรับนิพจน์ทั่วไป ไม่จำเป็นต้องมีห้องสมุด regexp4j;)
Andreas Dolk


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

มันจะส่งคืนสตริงเดิมหากไม่มี regex ที่ตรงกัน

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เพื่อทดสอบ regex

กลับกลายเป็นการดีกว่าที่จะเพิ่ม? หลังจาก * สำหรับการจับคู่น้อยลง อะไรทำนองนี้:

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
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.