2009-05-10 22 views
5


Tôi tự hỏi nếu ai đó có thể giúp tôi tìm ra cách để phân tích một chuỗi có định dạng sau:Phân tích một chuỗi chứa ký tự thoát sử dụng Java

;field1-field2-fieldN;field1-field2-fieldN; 

Mỗi bản ghi được giới hạn bởi ';' và mỗi trường trong một bản ghi được giới hạn bởi '-'. Biến chứng là các trường riêng lẻ có thể chứa các ký tự dấu phân cách thoát như vậy "\;" hoặc là "-". Điều này làm cho mã phân tích cú pháp đơn giản của tôi bên dưới thất bại. Vì vậy, những gì tôi đang cố gắng để làm là đến với biểu thức regex sẽ phù hợp với delimiters nhưng không phù hợp với delimiters thoát. kiến ​​thức regex của tôi không phải là tuyệt vời nhưng tôi mong đợi phải có một cách để kết hợp "([^ \;])" và "([;])" để có được những gì tôi yêu cầu.

public static List<ParsedRecord> parse(String data) { 
    List<ParsedRecord> parsedRecords = new List<ParsedRecord>(); 
    String[] records = data.split(";"); 
    for (String record : records) { 
     String[] fields = data.split("-"); 
     parsedRecords.add(new parsedRecord(fields)); 
    } 
    return parsedRecords; 
} 

Cảm ơn rất nhiều trước.

Trả lời

7

bạn có lẽ có thể tinh chỉnh biểu thức chính quy bạn sử dụng với phân chia như thế này:

split("[^\\];") 

Để chia ở bất cứ điều gì đó là một ";". nhưng không phải nếu trước đó có một "\". Và tương tự cho các dấu gạch ngang:

split("[^\\]-") 
+0

Cảm ơn! Tôi đã sử dụng kết hợp câu trả lời của bạn và Jon để làm cho trình phân tích cú pháp hoạt động. Nhiều đánh giá cao! –

+2

Điều này không hoàn toàn đúng ... regex được xác định ở trên sẽ có ký tự trước dấu phân tách bị tước bỏ. Vì vậy, "hello, thế giới" trở thành [địa ngục, thế giới]. Cách tốt hơn là sử dụng cái nhìn tiêu cực đằng sau cơ chế trong regex: http://stackoverflow.com/questions/820172/how-to-split-a-comma-separated-string-while-ignoring-escaped-commas – Alvin

7

Bạn có khả năng làm tốt nhất việc thực hiện thao tác không bị cắt và tách trong cùng một lần truyền. Tôi biết nó cảm thấy sai lầm về việc tách hai phần riêng biệt của chức năng, nhưng nó tránh một số trường hợp khó xử góc (ví dụ: "foo \; bar" chẳng hạn, trong đó; sau dấu gạch chéo ngược nhưng vẫn là dấu tách).

Dưới đây là một số mã cực kỳ đơn giản để thực hiện phân tích cú pháp - nó giả định rằng mọi dấu gạch chéo ngược về cơ bản có nghĩa là "xử lý ký tự tiếp theo dưới dạng đầu vào đơn giản" nhưng đó là tất cả.

import java.util.*; 

public class Test 
{ 
    public static void main(String[] args) 
    { 
     List<String> parsed = parse(args[0]); 
     for (String x : parsed) 
     { 
      System.out.println(x); 
     } 
    } 

    public static List<String> parse(String text) 
    { 
     List<String> ret = new ArrayList<String>(); 
     StringBuilder current = new StringBuilder(); 
     boolean escaping = false; 

     for (int i=0; i < text.length(); i++) 
     { 
      char c = text.charAt(i); 
      if (escaping) 
      { 
       current.append(c); 
       escaping = false; 
      } 
      else 
      { 
       if (c == '\\') 
       { 
        escaping = true; 
       } 
       else if (c == ';') 
       { 
        ret.add(current.toString()); 
        current = new StringBuilder(); 
       } 
       else 
       { 
        current.append(c); 
       } 
      } 
     } 
     if (escaping) 
     { 
      throw new IllegalArgumentException("Ended in escape sequence"); 
     } 
     ret.add(current.toString()); 
     return ret; 
    } 
} 

(Lưu ý rằng điều này không làm thay đổi việc bạn làm với ';' và cũng phản ứng với '-' - nguyên tắc là như nhau)

Các vấn đề liên quan