Java regex để trích xuất văn bản giữa các thẻ


82

Tôi có một tệp với một số thẻ tùy chỉnh và tôi muốn viết một biểu thức chính quy để trích xuất chuỗi giữa các thẻ. Ví dụ: nếu thẻ của tôi là:

[customtag]String I want to extract[/customtag]

Làm cách nào để viết một biểu thức chính quy để chỉ trích xuất chuỗi giữa các thẻ. Đoạn mã này có vẻ như là một bước đi đúng hướng:

Pattern p = Pattern.compile("[customtag](.+?)[/customtag]");
Matcher m = p.matcher("[customtag]String I want to extract[/customtag]");

Không biết phải làm gì tiếp theo. Có ý kiến ​​gì không? Cảm ơn.


1
Đối với người mới bắt đầu, bạn cần phải thoát khỏi []dấu ngoặc vuông là ký tự siêu trong một regex.
ridgerunner

Câu trả lời:


184

Bạn đang đi đúng hướng. Bây giờ bạn chỉ cần giải nén nhóm mong muốn, như sau:

final Pattern pattern = Pattern.compile("<tag>(.+?)</tag>", Pattern.DOTALL);
final Matcher matcher = pattern.matcher("<tag>String I want to extract</tag>");
matcher.find();
System.out.println(matcher.group(1)); // Prints String I want to extract

Nếu bạn muốn trích xuất nhiều lần truy cập, hãy thử cách này:

public static void main(String[] args) {
    final String str = "<tag>apple</tag><b>hello</b><tag>orange</tag><tag>pear</tag>";
    System.out.println(Arrays.toString(getTagValues(str).toArray())); // Prints [apple, orange, pear]
}

private static final Pattern TAG_REGEX = Pattern.compile("<tag>(.+?)</tag>", Pattern.DOTALL);

private static List<String> getTagValues(final String str) {
    final List<String> tagValues = new ArrayList<String>();
    final Matcher matcher = TAG_REGEX.matcher(str);
    while (matcher.find()) {
        tagValues.add(matcher.group(1));
    }
    return tagValues;
}

Tuy nhiên, tôi đồng ý rằng cụm từ thông dụng không phải là câu trả lời tốt nhất ở đây. Tôi muốn sử dụng XPath để tìm các phần tử mà tôi quan tâm. Xem API Java XPath để biết thêm thông tin.


3
Cảm ơn rất nhiều, đó chỉ là những gì tôi cần. Tôi sẽ xem xét XPath, nhưng bây giờ tôi nghĩ rằng giải pháp này sẽ hoạt động. Các ứng dụng của tôi rất đơn giản và có thể sẽ vẫn như vậy. Cảm ơn một lần nữa!
b10hazard

Còn về chuỗi này "<tag>apple</tag><b>hello</b><tag>orange</tag><tag>pear"? Làm thế nào chúng ta có thể nhận được pearmà không có thẻ đóng?
K.Sopheak

Để tổng quát hóa: private String extractDataFromTags (String tag) {Pattern pattern = Pattern.compile ("<. +?> (. +?) </.+?>"); Matcher matcher = pattern.matcher (thẻ); matcher.find (); return (matcher.group (1)); // In chuỗi tôi muốn trích xuất hoặc ném ngoại lệ}
PMateus

15

Thành thật mà nói, cụm từ thông dụng không phải là ý tưởng tốt nhất cho loại phân tích cú pháp này. Biểu thức chính quy bạn đã đăng có thể sẽ hoạt động tốt đối với các trường hợp đơn giản, nhưng nếu mọi thứ trở nên phức tạp hơn, bạn sẽ gặp phải vấn đề lớn (cùng một lý do tại sao bạn không thể phân tích cú pháp HTML bằng biểu thức chính quy một cách đáng tin cậy). Tôi biết bạn có thể không muốn nghe điều này, tôi biết tôi đã không làm thế khi hỏi cùng một loại câu hỏi, nhưng phân tích cú pháp chuỗi đã trở nên đáng tin cậy hơn đối với tôi sau khi tôi ngừng cố gắng sử dụng biểu thức chính quy cho mọi thứ.

jTopas là một trình phân tích cú pháp TUYỆT ĐỐI giúp bạn viết trình phân tích cú pháp bằng tay khá dễ dàng (Tôi MẠNH MẼ đề xuất jtopas trên các thư viện java scanner / etc .. tiêu chuẩn). Nếu bạn muốn xem jtopas trong hành động, đây là một số phân tích cú pháp tôi đã viết bằng jTopas để phân tích này loại tập tin

Nếu bạn đang phân tích cú pháp tệp XML, bạn nên sử dụng thư viện trình phân tích cú pháp xml. Đừng tự làm điều đó trừ khi bạn chỉ làm điều đó cho vui, có rất nhiều lựa chọn đã được chứng minh trên mạng


Cám ơn vì sự gợi ý. Tôi đã đánh dấu chúng và chắc chắn tôi sẽ xem xét sử dụng nó trong các dự án trong tương lai. Hiện tại, phương pháp regex có lẽ là phương pháp tôi sẽ sử dụng vì tệp tôi đang phân tích cú pháp rất nhỏ / đơn giản.
b10hazard

7

Một cách tiếp cận chung chung, đơn giản hơn và một chút nguyên thủy để tìm thẻ, thuộc tính và giá trị

    Pattern pattern = Pattern.compile("<(\\w+)( +.+)*>((.*))</\\1>");
    System.out.println(pattern.matcher("<asd> TEST</asd>").find());
    System.out.println(pattern.matcher("<asd TEST</asd>").find());
    System.out.println(pattern.matcher("<asd attr='3'> TEST</asd>").find());
    System.out.println(pattern.matcher("<asd> <x>TEST<x>asd>").find());
    System.out.println("-------");
    Matcher matcher = pattern.matcher("<as x> TEST</as>");
    if (matcher.find()) {
        for (int i = 0; i <= matcher.groupCount(); i++) {
            System.out.println(i + ":" + matcher.group(i));
        }
    }

Mẫu sẽ như thế nào Nếu có một chuỗi các thẻ khác nhau hoặc các thẻ lồng nhau như <h2>Mac</h2><h1>loves it</h1>hoặc <h2>Mac<h1>liked your answer</h1></h2>?
MAC

1
vui lòng chỉnh sửa i <matcher.groupCount (); thành i <= matcher.groupCount (); để bao gồm chuỗi con phù hợp đầu tiên tức là. ở chỉ số 0
AVA

4

Thử đi:

Pattern p = Pattern.compile(?<=\\<(any_tag)\\>)(\\s*.*\\s*)(?=\\<\\/(any_tag)\\>);
Matcher m = p.matcher(anyString);

Ví dụ:

String str = "<TR> <TD>1Q Ene</TD> <TD>3.08%</TD> </TR>";
Pattern p = Pattern.compile("(?<=\\<TD\\>)(\\s*.*\\s*)(?=\\<\\/TD\\>)");
Matcher m = p.matcher(str);
while(m.find()){
   Log.e("Regex"," Regex result: " + m.group())       
}

Đầu ra:

10 Ene

3,08%


2
    final Pattern pattern = Pattern.compile("tag\\](.+?)\\[/tag");
    final Matcher matcher = pattern.matcher("[tag]String I want to extract[/tag]");
    matcher.find();
    System.out.println(matcher.group(1));

thế còn tiền tố cho thẻ (nếu tiền tố là động)
user1514499

2
    String s = "<B><G>Test</G></B><C>Test1</C>";

    String pattern ="\\<(.+)\\>([^\\<\\>]+)\\<\\/\\1\\>";

       int count = 0;

        Pattern p = Pattern.compile(pattern);
        Matcher m =  p.matcher(s);
        while(m.find())
        {
            System.out.println(m.group(2));
            count++;
        }

1

Tôi đặt tiền tố cho câu trả lời này bằng "bạn không nên sử dụng một biểu thức chính quy để phân tích cú pháp XML - nó chỉ dẫn đến các trường hợp cạnh không hoạt động đúng và regex ngày càng phức tạp trong khi bạn cố gắng sửa nó . "

Điều đó đang được nói, bạn cần phải tiếp tục bằng cách khớp chuỗi và lấy nhóm bạn muốn:

if (m.matches())
{
   String result = m.group(1);
   // do something with result
}
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.