Sử dụng Java để tìm chuỗi con của chuỗi lớn hơn bằng Biểu thức chính quy


140

Nếu tôi có một chuỗi như thế này:

FOO[BAR]

Tôi cần một cách chung để đưa chuỗi "BAR" ra khỏi chuỗi để bất kể chuỗi nào nằm giữa dấu ngoặc vuông, nó sẽ có thể lấy chuỗi.

ví dụ

FOO[DOG] = DOG
FOO[CAT] = CAT

Câu trả lời:


253

Bạn sẽ có thể sử dụng các bộ lượng hóa không tham lam, cụ thể là *?. Bạn sẽ có thể muốn như sau:

Pattern MY_PATTERN = Pattern.compile("\\[(.*?)\\]");

Điều này sẽ cung cấp cho bạn một mẫu sẽ khớp với chuỗi của bạn và đặt văn bản trong dấu ngoặc vuông trong nhóm đầu tiên. Hãy xem Tài liệu API mẫu để biết thêm thông tin.

Để trích xuất chuỗi, bạn có thể sử dụng một cái gì đó như sau:

Matcher m = MY_PATTERN.matcher("FOO[BAR]");
while (m.find()) {
    String s = m.group(1);
    // s now contains "BAR"
}

16
Điều đáng nói là nếu có một dòng mới giữa các dấu ngoặc vuông, điều này sẽ thất bại và bạn nên sử dụng cờ Pattern.DOTALL để tránh điều đó.
cletus

Sử dụng mẫu trên, sau đó bạn sẽ sử dụng mẫu đó như thế nào để trích xuất chuỗi chứa chuỗi BAR? Tôi đang xem API mẫu và API đối sánh nhưng tôi vẫn không chắc chắn làm thế nào để có được chuỗi đó.
digiarnie

@cletus: Gọi tốt! @digiarnie: Tôi đã thêm một bản sửa đổi cho câu trả lời có chứa một số mã người rơm để có được trận đấu.
Bryan Kyle

30

cách không regex:

String input = "FOO[BAR]", extracted;
extracted = input.substring(input.indexOf("["),input.indexOf("]"));

cách khác, để sử dụng hiệu năng / bộ nhớ tốt hơn một chút (cảm ơn Hosam):

String input = "FOO[BAR]", extracted;
extracted = input.substring(input.indexOf('['),input.lastIndexOf(']'));

1
Tôi sẽ sử dụng lastIndexOf(']')thay thế, mà sẽ xử lý dấu ngoặc lồng. Ngoài ra, tôi tin rằng việc sử dụng indexOf(char)sẽ nhanh hơn indexOf(String).
Hosam Aly

Không có gì. Lưu ý của bạn về hiệu suất cũng rất phù hợp, vì lastIndexOfchắc chắn sẽ nhanh hơn để tìm khung đóng cửa.
Hosam Aly

3
cái gì nhanh hơn, chuỗi con indexof, v.v. hay regrec?
Toskan

2
xem giá trị của Amit cho "trích xuất" bên dưới: input.indexOf ('[') + 1
gcbound

28

Đây là một ví dụ hoạt động:

RegapiExample.java

package org.regexp.replace;

import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class RegexpExample
{
    public static void main(String[] args)
    {
        String string = "var1[value1], var2[value2], var3[value3]";
        Pattern pattern = Pattern.compile("(\\[)(.*?)(\\])");
        Matcher matcher = pattern.matcher(string);

        List<String> listMatches = new ArrayList<String>();

        while(matcher.find())
        {
            listMatches.add(matcher.group(2));
        }

        for(String s : listMatches)
        {
            System.out.println(s);
        }
    }
}

Nó sẽ hiển thị :

value1
value2
value3

6
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public static String get_match(String s, String p) {
    // returns first match of p in s for first group in regular expression 
    Matcher m = Pattern.compile(p).matcher(s);
    return m.find() ? m.group(1) : "";
}

get_match("FOO[BAR]", "\\[(.*?)\\]")  // returns "BAR"

public static List<String> get_matches(String s, String p) {
    // returns all matches of p in s for first group in regular expression 
    List<String> matches = new ArrayList<String>();
    Matcher m = Pattern.compile(p).matcher(s);
    while(m.find()) {
        matches.add(m.group(1));
    }
    return matches;
}

get_matches("FOO[BAR] FOO[CAT]", "\\[(.*?)\\]")) // returns [BAR, CAT]

5

Nếu bạn chỉ cần lấy bất cứ thứ gì ở giữa [], bạn có thể sử dụng \[([^\]]*)\]như thế này:

Pattern regex = Pattern.compile("\\[([^\\]]*)\\]");
Matcher m = regex.matcher(str);
if (m.find()) {
    result = m.group();
}

Nếu bạn cần nó phải ở dạng identifier + [ + content + ]thì bạn chỉ có thể giới hạn trích xuất nội dung khi mã định danh là một chữ số:

[a-zA-Z][a-z-A-Z0-9_]*\s*\[([^\]]*)\]

Điều này sẽ xác nhận những thứ như Foo [Bar], hoặc myDevice_123["input"]ví dụ.

Vấn đề chính

Vấn đề chính là khi bạn muốn trích xuất nội dung của một cái gì đó như thế này:

FOO[BAR[CAT[123]]+DOG[FOO]]

Regex sẽ không hoạt động và sẽ trở lại BAR[CAT[123FOO.
Nếu chúng tôi thay đổi Regex thành \[(.*)\]thì chúng tôi sẽ ổn nhưng sau đó, nếu bạn đang cố trích xuất nội dung từ những thứ phức tạp hơn như:

FOO[BAR[CAT[123]]+DOG[FOO]] = myOtherFoo[BAR[5]]

Không có Regexes nào hoạt động.

Regex chính xác nhất để trích xuất nội dung phù hợp trong mọi trường hợp sẽ phức tạp hơn rất nhiều vì nó cần phải cân bằng []các cặp và cung cấp cho bạn nội dung chúng.

Một giải pháp đơn giản hơn

Nếu các vấn đề của bạn trở nên phức tạp và nội dung []tùy ý, thay vào đó, bạn có thể cân bằng các cặp []và trích xuất chuỗi bằng cách sử dụng mã cũ đơn giản hơn so với Regex:

int i;
int brackets = 0;
string c;
result = "";
for (i = input.indexOf("["); i < str.length; i++) {
    c = str.substring(i, i + 1);
    if (c == '[') {
        brackets++;
    } else if (c == ']') {
        brackets--;
        if (brackets <= 0) 
            break;
    }
    result = result + c;
}   

Đây là mã giả nhiều hơn mã thực, tôi không phải là người viết mã Java nên tôi không biết cú pháp có đúng không, nhưng nó đủ dễ để cải thiện.
Điều quan trọng là mã này sẽ hoạt động và cho phép bạn trích xuất nội dung của nó [], tuy nhiên nó phức tạp.


2

Tôi nghĩ rằng biểu hiện thường xuyên của bạn sẽ trông như sau:

/FOO\[(.+)\]/

Giả sử rằng FOO sẽ không đổi.

Vì vậy, để đưa cái này vào Java:

Pattern p = Pattern.compile("FOO\\[(.+)\\]");
Matcher m = p.matcher(inputLine);

FOO [BAR] FOO [BAZ] -> với regex của bạn sẽ trở lại: "BAR] FOO [BAZ"
Mohammad Jafar Mashhadi

1
String input = "FOO[BAR]";
String result = input.substring(input.indexOf("[")+1,input.lastIndexOf("]"));

Điều này sẽ trả về giá trị giữa đầu tiên '[' và cuối ']'

Foo [Thanh] => Thanh

Foo [Thanh [kiểm tra]] => Thanh [kiểm tra]

Lưu ý: Bạn nên thêm kiểm tra lỗi nếu chuỗi đầu vào không được định dạng tốt.


0

giả sử rằng không có dấu ngoặc vuông đóng nào khác được cho phép trong, / FOO \ [([^ \]] *) \] /


0

Tôi xác định rằng tôi muốn số lượng ký tự không tối đa giữa []. Những cái này cần phải được thoát bằng dấu gạch chéo ngược (và trong Java, những cái này cần phải được thoát lại một lần nữa) và định nghĩa của non-] là một lớp ký tự, do đó bên trong [](nghĩa là [^\\]]). Kết quả:

FOO\\[([^\\]]+)\\]

0

Giống như nó hoạt động nếu bạn muốn phân tích một số chuỗi đến từ mYearInDB.toString () = [2013], nó sẽ cung cấp cho năm 2013

Matcher n = MY_PATTERN.matcher("FOO[BAR]"+mYearInDB.toString());
while (n.find()) {
 extracredYear  = n.group(1);
 // s now contains "BAR"
    }
    System.out.println("Extrated output is : "+extracredYear);

0

Regrec này hoạt động với tôi:

form\[([^']*?)\]

thí dụ:

form[company_details][0][name]
form[company_details][0][common_names][1][title]

đầu ra:

Match 1
1.  company_details
Match 2
1.  company_details

Đã thử nghiệm trên http://rubular.com/


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.