2012-05-22 47 views
7

Tôi muốn chia chuỗi có khoảng trắng phân cách. nhưng nó sẽ xử lý các chuỗi được trích dẫn một cách thông minh. Ví dụ. cho một chuỗi nhưTách chuỗi được trích dẫn với dấu phân tách

"John Smith" Ted Barry 

Nó sẽ trả lại ba chuỗi John Smith, Ted và Barry.

+2

Bạn có thể cần phân tách các chuỗi được trích dẫn đầu tiên, sau đó chia phần còn lại của chuỗi theo khoảng trắng. Phải có một số câu hỏi xung quanh ở đây về cách thực hiện bước đầu tiên. Bước thứ hai là tầm thường. – jahroy

+1

Và bạn đã thử những gì? –

+2

Một thư viện phân tích cú pháp CSV phong nha sẽ hoạt động tốt cho bạn. Hầu hết sẽ cho phép lựa chọn dấu phân cách và sẽ tôn trọng và tránh tách văn bản được trích dẫn. –

Trả lời

10

Sau khi làm rối tung nó, bạn có thể sử dụng Regex cho việc này. Chạy tương đương với "phù hợp với tất cả" trên:

((?<=("))[\w ]*(?=("(\s|$))))|((?<!")\w+(?!")) 

Một Java Ví dụ:

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

public class Test 
{ 
    public static void main(String[] args) 
    { 
     String someString = "\"Multiple quote test\" not in quotes \"inside quote\" \"A work in progress\""; 
     Pattern p = Pattern.compile("((?<=(\"))[\\w ]*(?=(\"(\\s|$))))|((?<!\")\\w+(?!\"))"); 
     Matcher m = p.matcher(someString); 

     while(m.find()) { 
      System.out.println("'" + m.group() + "'"); 
     } 
    } 
} 

Output:

'Multiple quote test' 
'not' 
'in' 
'quotes' 
'inside quote' 
'A work in progress' 

Các sự cố biểu hiện thường xuyên với các ví dụ sử dụng trên có thể được xem tại đây :

http://regex101.com/r/wM6yT9


Với tất cả những gì đã nói, cụm từ thông dụng không nên là giải pháp cho mọi thứ - tôi chỉ vui vẻ. Ví dụ này có rất nhiều trường hợp cạnh như xử lý các ký tự unicode, ký hiệu, vv Bạn nên sử dụng thư viện đã thử và đúng cho loại công việc này. Hãy xem các câu trả lời khác trước khi sử dụng câu trả lời này.

+0

Tôi không chắc chắn nếu đầu vào có chứa Unicode hay không, nhưng mã của bạn sẽ không thể để xử lý nó. – nhahtdh

+0

đây là một ví dụ điển hình. 1, tại sao bạn không đặt một nếu để kiểm tra nếu m.group() trả về một không gian trống, theo cách đó bạn không phải xuất ra các khoảng trống. –

+0

Brilliant ... +1 –

4

Hãy thử mã bit xấu xí này.

String str = "hello my dear \"John Smith\" where is Ted Barry"; 
    List<String> list = Arrays.asList(str.split("\\s")); 
    List<String> resultList = new ArrayList<String>(); 
    StringBuilder builder = new StringBuilder(); 
    for(String s : list){ 
     if(s.startsWith("\"")) { 
      builder.append(s.substring(1)).append(" "); 
     } else { 
      resultList.add((s.endsWith("\"") 
        ? builder.append(s.substring(0, s.length() - 1)) 
        : builder.append(s)).toString()); 
      builder.delete(0, builder.length()); 
     } 
    } 
    System.out.println(resultList);  
+0

Tốt hơn nhiều so với mã của tôi. +1 –

+0

Không gian trống quá mức sẽ khiến chương trình tạo chuỗi trống. – nhahtdh

+0

@nhahtdh: O'yeah. Tôi chỉ cung cấp một gợi ý, thực sự. Không phải là giải pháp làm việc 100%. Trevor Senior, đóng đinh nó xuống tốt. Điều đó cũng có một vấn đề tương tự của không gian trống, mặc dù. Nhưng đó không phải là một vấn đề thực sự và có thể được sửa dễ dàng. –

1

commons-lang có lớp StrTokenizer để thực hiện việc này cho bạn và cũng có thư viện java-csv.

Ví dụ với StrTokenizer:

String params = "\"John Smith\" Ted Barry" 
// Initialize tokenizer with input string, delimiter character, quote character 
StrTokenizer tokenizer = new StrTokenizer(params, ' ', '"'); 
for (String token : tokenizer.getTokenArray()) { 
    System.out.println(token); 
} 

Output:

John Smith 
Ted 
Barry 
+0

@BasilioGerman Tôi đã thêm một ví dụ để bạn có thể cân nhắc xóa nhận xét của mình. –

3

tốt, tôi làm một snipet nhỏ mà làm những gì bạn muốn và một số thứ khác. vì bạn không chỉ định nhiều điều kiện hơn nên tôi đã không gặp rắc rối. tôi biết đây là một cách bẩn thỉu và bạn có thể có được kết quả tốt hơn với một cái gì đó đã được thực hiện. nhưng đối với niềm vui lập trình ở đây là ví dụ:

String example = "hello\"John Smith\" Ted Barry lol\"Basi German\"hello"; 
    int wordQuoteStartIndex=0; 
    int wordQuoteEndIndex=0; 

    int wordSpaceStartIndex = 0; 
    int wordSpaceEndIndex = 0; 

    boolean foundQuote = false; 
    for(int index=0;index<example.length();index++) { 
     if(example.charAt(index)=='\"') { 
      if(foundQuote==true) { 
       wordQuoteEndIndex=index+1; 
       //Print the quoted word 
       System.out.println(example.substring(wordQuoteStartIndex, wordQuoteEndIndex));//here you can remove quotes by changing to (wordQuoteStartIndex+1, wordQuoteEndIndex-1) 
       foundQuote=false; 
       if(index+1<example.length()) { 
        wordSpaceStartIndex = index+1; 
       } 
      }else { 
       wordSpaceEndIndex=index; 
       if(wordSpaceStartIndex!=wordSpaceEndIndex) { 
        //print the word in spaces 
        System.out.println(example.substring(wordSpaceStartIndex, wordSpaceEndIndex)); 
       } 
       wordQuoteStartIndex=index; 
       foundQuote = true; 
      } 
     } 

     if(foundQuote==false) { 
      if(example.charAt(index)==' ') { 
       wordSpaceEndIndex = index; 
       if(wordSpaceStartIndex!=wordSpaceEndIndex) { 
        //print the word in spaces 
        System.out.println(example.substring(wordSpaceStartIndex, wordSpaceEndIndex)); 
       } 
       wordSpaceStartIndex = index+1; 
      } 

      if(index==example.length()-1) { 
       if(example.charAt(index)!='\"') { 
        //print the word in spaces 
        System.out.println(example.substring(wordSpaceStartIndex, example.length())); 
       } 
      } 
     } 
    } 

điều này cũng kiểm tra các từ không được phân cách bằng khoảng trắng sau hoặc trước dấu ngoặc kép, chẳng hạn như từ "hello" trước "John Smith" và sau "Basi Đức".

khi chuỗi được sửa đổi để "John Smith" Ted Barry đầu ra là ba chuỗi, 1) "John Smith" 2) Ted 3) Barry

Các chuỗi trong ví dụ này là hello "John Smith" Ted Barry lol "Basi Đức" hello và in 1) chào 2) "John Smith" 3) Ted 4) Barry 5) lol 6) "Basi Đức" 7) chào

Hy vọng nó giúp

+1

Đây là mã tốt nhất trong số tất cả những điều này. Nó có thể xử lý đầu vào Unicode và không tạo ra các chuỗi rỗng khi có quá nhiều khoảng trống. Nó sẽ giữ tất cả mọi thứ bên trong báo giá còn nguyên vẹn (tốt, điều này có thể là một cộng hoặc trừ). Tôi nghĩ rằng mã có thể được sửa đổi một chút để loại bỏ các dấu ngoặc kép. Mở rộng hơn nữa có thể là: thêm hỗ trợ cho báo giá thoát. – nhahtdh

+0

Chắc chắn, các dấu ngoặc kép có thể bị xóa. chỉ tôi đã làm cho nó trên pupose để giữ dấu ngoặc kép. ive thêm ý kiến ​​về nơi để loại bỏ các dấu ngoặc kép. –

1

Đây là phiên bản của riêng tôi, dọn dẹp từ http://pastebin.com/aZngu65y (được đăng trong nhận xét). Nó có thể quản lý Unicode. Nó sẽ dọn dẹp tất cả các khoảng trống quá mức (ngay cả trong báo giá) - điều này có thể tốt hay xấu tùy thuộc vào nhu cầu. Không hỗ trợ cho báo giá thoát.

private static String[] parse(String param) { 
    String[] output; 

    param = param.replaceAll("\"", " \" ").trim(); 
    String[] fragments = param.split("\\s+"); 

    int curr = 0; 
    boolean matched = fragments[curr].matches("[^\"]*"); 
    if (matched) curr++; 

    for (int i = 1; i < fragments.length; i++) { 
    if (!matched) 
     fragments[curr] = fragments[curr] + " " + fragments[i]; 

    if (!fragments[curr].matches("(\"[^\"]*\"|[^\"]*)")) 
     matched = false; 
    else { 
     matched = true; 

     if (fragments[curr].matches("\"[^\"]*\"")) 
     fragments[curr] = fragments[curr].substring(1, fragments[curr].length() - 1).trim(); 

     if (fragments[curr].length() != 0) 
     curr++; 

     if (i + 1 < fragments.length) 
     fragments[curr] = fragments[i + 1]; 
    } 
    } 

    if (matched) { 
    return Arrays.copyOf(fragments, curr); 
    } 

    return null; // Parameter failure (double-quotes do not match up properly). 
} 

mẫu đầu vào để so sánh:

"sdfskjf" sdfjkhsd "hfrif ehref" "fksdfj sdkfj fkdsjf" sdf sfssd 


asjdhj sdf ffhj "fdsf fsdjh" 
日本語 中文 "Tiếng Việt" "English" 
    dsfsd  
    sdf  " s dfs fsd f " sd f fs df fdssf "日本語 中文" 
"" ""  "" 
" sdfsfds " "f fsdf 

(2 dòng là trống rỗng, dòng thứ 3 là không gian, dòng cuối cùng là bị thay đổi). Hãy đánh giá với kết quả mong đợi của riêng bạn, vì nó có thể thay đổi, nhưng đường cơ sở là, trường hợp thứ nhất nên trả về [sdfskjf, sdfjkhsd, hfrif ehref, fksdfj sdkfj fkdsjf, sdf, sfssd].

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