2011-02-10 66 views
14

Tôi đang cố gắng để thực hiện một số file log phân tích o siêu đơn giản, vì vậy tôi đang sử dụng String.split phương pháp như thế này:thoát dấu phẩy khi sử dụng String.split

String [] parts = input.split(","); 

Và hoạt động tuyệt vời cho đầu vào như:

a,b,c 

Hoặc

type=simple, output=Hello, repeat=true 

Chỉ cần nói điều gì đó.

Làm cách nào để thoát khỏi dấu phẩy, vì vậy nó không khớp với dấu phẩy trung gian?

Ví dụ, nếu tôi muốn bao gồm một dấu phẩy trong một trong những phần:

type=simple, output=Hello, world, repeate=true 

Tôi đã suy nghĩ trong một cái gì đó như:

type=simple, output=Hello\, world, repeate=true 

Nhưng tôi không biết làm thế nào để tạo ra phần tách để tránh khớp với dấu phẩy.

Tôi đã thử:

String [] parts = input.split("[^\,],"); 

Nhưng, tốt, không hoạt động.

+0

Tôi sẽ upvote câu hỏi của bạn trong 2 giờ (! Tôi ra khỏi phiếu cho ngày hôm nay) – aioobe

+0

Ổi Issue 412: Thêm chức năng thoát để Joiner và Splitter http://goo.gl/pfSCb – oluies

+0

@oluies: -O OscarRyz

Trả lời

21

Bạn có thể giải quyết bằng cách sử dụng negative look behind.

String[] parts = str.split("(?<!\\\\), "); 

Về cơ bản nó nói, chia trên mỗi ", " không được preceeded bởi một dấu chéo ngược.

String str = "type=simple, output=Hello\\, world, repeate=true"; 
String[] parts = str.split("(?<!\\\\), "); 
for (String s : parts) 
    System.out.println(s); 

Output:

type=simple 
output=Hello\, world 
repeate=true 

(ideone.com link)


Nếu bạn tình cờ bị mắc kẹt với các giá trị phi trốn thoát bằng dấu phẩy, bạn có thể làm như sau (tương tự) hack:

String[] parts = str.split(", (?=\\w+=)"); 

Mà nói chia trên mỗi ", " được theo sau bởi một số word-nhân vật và một =

(ideone.com link)

+1

Khá là một câu trả lời thú vị, nhưng không phải câu hỏi của anh ấy 'Làm thế nào tôi có thể thoát khỏi dấu phẩy, Vì vậy, nó không phù hợp với dấu phẩy trung gian? ' – Zeemee

+2

Giải pháp tốt, nhưng IMHO cho vấn đề sai. Trong khi một chuỗi như vậy có thể được phân tích bằng cách sử dụng này, nó sẽ thất bại một ngày với ai đó nói 'type = simple, output = Hello, world, repeat = cho đến ngày mai, hoặc có thể cho đến 0 = 1'. Tôi muốn đề xuất một cơ chế thoát thích hợp thay vì quá thông minh. – maaartinus

+0

Điểm tốt. Thành thật mà nói, tôi hiểu sai câu hỏi. Đã cập nhật. – aioobe

0

Tôi nghĩ

input.split("[^\\\\],"); 

nên làm việc. Nó sẽ phân chia ở tất cả các dấu phẩy không có dấu gạch chéo ngược. BTW nếu bạn đang làm việc với Eclipse, tôi có thể đề xuất Plugin QuickRex để kiểm tra và gỡ lỗi Regexes.

+0

Điều này gần như đúng, nhưng không hoàn hảo vì nó không cho phép thoát các dấu gạch chéo ngược. Nó sẽ ăn nhân vật trước dấu gạch chéo ngược. Một lookbehind sẽ làm. – maaartinus

+0

Tôi không gặp vấn đề gì với việc khác: P Đang cố gắng ... – OscarRyz

+1

@maaartinus: Có, bạn đúng ... – Zeemee

4

Tôi sợ, không có giải pháp hoàn hảo cho String.split. Sử dụng một matcher cho ba phần sẽ làm việc.Trong trường hợp số lượng bộ phận không phải là hằng số, tôi khuyên bạn nên sử dụng vòng lặp với matcher.find. Một cái gì đó như thế này có lẽ

final String s = "type=simple, output=Hello, world, repeat=true"; 
final Pattern p = Pattern.compile("((?:[^\\\\,]|\\\\.)*)(?:,|$)"); 
final Matcher m = p.matcher(s); 
while (m.find()) System.out.println(m.group(1)); 

Bạn có lẽ sẽ muốn bỏ qua các khoảng trống sau dấu phẩy cũng như:

final Pattern p = Pattern.compile("((?:[^\\\\,]|\\\\.)*)(?:,\\s*|$)"); 

Nó không thực sự phức tạp, chỉ cần lưu ý rằng bạn cần bốn backslashes để phù hợp với một .

+0

+1 Vẫn nhai rằng ... – OscarRyz

+0

Thật dễ dàng: Nhóm là một chuỗi gồm 1. ký tự bình thường (ví dụ: ngoại trừ dấu gạch chéo ngược và dấu phẩy) và 2. bất kỳ ký tự thoát nào (tức là dấu gạch chéo ngược theo sau là bất kỳ thứ gì). Phần còn lại là dấu phẩy tách hoặc dấu kết thúc. – maaartinus

+0

Nếu bạn sử dụng tuyến Pattern/Matcher, sẽ có một 'matcher đơn giản hơn.find' giải pháp có thể tìm thấy một cặp khóa/giá trị tại một thời điểm, không? – aioobe

2

Thoát làm việc với trái ngược với câu trả lời aioobe của (Cập nhật: aioobe bây giờ sử dụng các cấu trúc tương tự, nhưng tôi không biết rằng khi tôi viết bài này), lookbehind tiêu cực

final String s = "type=simple, output=Hello\\, world, repeate=true"; 
final String[] tokens = s.split("(?<!\\\\),\\s*"); 
for(final String item : tokens){ 
    System.out.println("'" + item.replace("\\,", ",") + "'"); 
} 

Output:

'type = đơn giản'
'output = Hello, world'
'repeate = true'

tham khảo:

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