2010-02-22 36 views
12

Tôi đã hỏi câu hỏi này trước đó và nó đã bị đóng vì đó là một bản sao, mà tôi chấp nhận và thực sự tìm thấy câu trả lời trong câu hỏi Java: splitting a comma-separated string but ignoring commas in quotes, vì vậy nhờ bất kỳ ai được đăng nó.Tách một chuỗi trên dấu phẩy không có trong dấu ngoặc kép với một twist

Nhưng tôi đã gặp phải sự cố khác. Rõ ràng những gì tôi cần làm là sử dụng "," như dấu phân cách của tôi khi có số không hoặc thậm chí một số dấu ngoặc kép, nhưng cũng bỏ qua bất kỳ "," chứa trong dấu ngoặc đơn.

Vì vậy, như sau:

"Thanks,", "in advance,", "for("the", "help")" 

Sẽ tokenize như:

  • Cảm ơn,
  • trước,
  • cho ("the", "giúp đỡ")

Tôi không chắc chắn liệu có chỉnh sửa regex hiện tại hay không đang sử dụng để cho phép điều này, nhưng bất kỳ hướng dẫn nào cũng sẽ được đánh giá cao.

line.split(",(?=([^\"]*\"[^\"]*\")*[^\"]*$)"); 
+0

Kết quả mong muốn là gì? – DOK

+12

Bạn nên sử dụng trình phân tích cú pháp CSV thực để xử lý sự lộn xộn đó. Không ** mọi vấn đề phân tích cú pháp ** đều được xử lý tốt nhất với các regex. –

+1

@Joachim, Bạn biết bao nhiêu trình phân tích cú pháp CSV có thể xử lý các dấu ngoặc kép, dấu ngoặc bên trong, dấu ngoặc kép bên trong theo cách mà anh ta muốn? –

Trả lời

5

Đôi khi nó là dễ dàng hơn để phù hợp với những gì bạn muốn thay vì những gì bạn không muốn:

String s = "\"Thanks,\", \"in advance,\", \"for(\"the\", \"help\")\""; 
String regex = "\"(\\([^)]*\\)|[^\"])*\""; 
Pattern p = Pattern.compile(regex); 
Matcher m = p.matcher(s); 
while(m.find()) { 
    System.out.println(s.substring(m.start(),m.end())); 
} 

Output:

"Thanks," 
"in advance," 
"for("the", "help")" 

Nếu bạn cũng cần nó để bỏ qua đóng ngoặc bên trong các phần trích dẫn nằm trong dấu ngoặc vuông, sau đó bạn cần điều này:

String regex = "\"(\\((\"[^\"]*\"|[^)])*\\)|[^\"])*\""; 

Một ví dụ về một chuỗi mà cần thứ hai này, phiên bản phức tạp hơn là:

"foo","bar","baz(":-)",":-o")" 

Output:

"foo" 
"bar" 
"baz(":-)",":-o")" 

Tuy nhiên, tôi muốn khuyên bạn nên thay đổi định dạng dữ liệu của bạn nếu có thể . Điều này sẽ dễ dàng hơn rất nhiều nếu bạn sử dụng một định dạng chuẩn như XML để lưu trữ mã thông báo của bạn.

3

A nhà phát triển nội bộ trình phân tích cú pháp có thể dễ dàng được viết.

Ví dụ, ANTLR ngữ pháp này sẽ chăm sóc của ví dụ đầu vào của bạn mà không cần nhiều rắc rối:

parse 
    : line* 
    ; 

line 
    : Quoted (',' Quoted)* ('\r'? '\n' | EOF) 
    ; 

Quoted 
    : '"' (Atom)* '"' 
    ; 

fragment 
Atom 
    : Parentheses 
    | ~('"' | '\r' | '\n' | '(' | ')') 
    ; 

fragment 
Parentheses 
    : '(' ~('(' | ')' | '\r' | '\n')* ')' 
    ; 

Space 
    : (' ' | '\t') {skip();} 
    ; 

và nó sẽ được dễ dàng để mở rộng này có dấu ngoặc kép thoát hoặc ngoặc vào tài khoản.

Khi ăn các phân tích cú pháp được tạo ra bởi văn phạm đó để sau hai dòng đầu vào:

"Thanks,", "in advance,", "for("the", "help")" 
"and(,some,more)","data , here" 

nó được phân tích như thế này:

alt text http://i47.tinypic.com/258otvs.png

Nếu bạn xem xét để sử dụng ANTLR cho điều này, Tôi có thể đăng một ít CÁCH để có được một trình phân tích cú pháp từ ngữ pháp mà tôi đã đăng, nếu bạn muốn.

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