2013-03-02 2 views
3

мне нужно написать регулярное выражение для строки чтения из файларегулярное выражение для »в Java

 
apple,boy,cat,"dog,cat","time\" after\"noon" 

Мне нужно разбить его на

 
apple 
boy 
cat 
dog,cat 
time"after"noon 

Я попытался с помощью

Pattern pattern = 
Pattern.compile("[\\\"]"); 
String items[]=pattern.split(match); 

для второй части, но я не мог получить правильный ответ, не могли бы вы мне помочь?

+0

Зачем вам нужно использовать регулярное выражение? Вы можете заменить «\» пустым пространством после разделения на запятую? – 2013-03-02 21:41:49

+0

Попробуйте изменить ваше регулярное выражение на «\\\» «это поможет немного, но не приведет вас к вашей конечной цели. – Scott

+2

Регулярное выражение не может выполнить то, что вы пытаетесь сделать. Рассмотрим, что произойдет, если вы попытаетесь разобрать эту строку : «apple, boy», «C: \\», «dog, cat» «Вместо обычного выражения я рекомендую вам просто читать символы один за другим и обрабатывать обратную косую черту в вашем собственном коде. – VGR

ответ

3

Поскольку ваш вопрос больше проблемы синтаксического анализа, чем регулярное выражение проблемы, вот другое решение, которое будет работать:

public class CsvReader { 

    Reader r; 
    int row, col; 
    boolean endOfRow; 

    public CsvReader(Reader r){ 
     this.r = r instanceof BufferedReader ? r : new BufferedReader(r); 
     this.row = -1; 
     this.col = 0; 
     this.endOfRow = true; 
    } 

    /** 
    * Returns the next string in the input stream, or null when no input is left 
    * @return 
    * @throws IOException 
    */ 
    public String next() throws IOException { 
     int i = r.read(); 
     if(i == -1) 
      return null; 

     if(this.endOfRow){ 
      this.row++; 
      this.col = 0; 
      this.endOfRow = false; 
     } else { 
      this.col++; 
     } 

     StringBuilder b = new StringBuilder(); 
outerLoop: 
     while(true){ 
      char c = (char) i; 
      if(i == -1) 
       break; 
      if(c == ','){ 
       break; 
      } else if(c == '\n'){ 
       endOfRow = true; 
       break; 
      } else if(c == '\\'){ 
       i = r.read(); 
       if(i == -1){ 
        break; 
       } else { 
        b.append((char)i); 
       } 
      } else if(c == '"'){ 
       while(true){ 
        i = r.read(); 

        if(i == -1){ 
         break outerLoop; 
        } 
        c = (char)i; 
        if(c == '\\'){ 
         i = r.read(); 
         if(i == -1){ 
          break outerLoop; 
         } else { 
          b.append((char)i); 
         } 
        } else if(c == '"'){ 
         r.mark(2); 
         i = r.read(); 
         if(i == '"'){ 
          b.append('"'); 
         } else { 
          r.reset(); 
          break; 
         } 
        } else { 
         b.append(c); 
        } 
       } 
      } else { 
       b.append(c); 
      } 
      i = r.read(); 
     } 

     return b.toString().trim(); 
    } 


    public int getColNum(){ 
     return col; 
    } 

    public int getRowNum(){ 
     return row; 
    } 

    public static void main(String[] args){ 

     try { 
      String input = "apple,boy,cat,\"dog,cat\",\"time\\\" after\\\"noon\"\nquick\"fix\" hello, \"\"\"who's there?\""; 
      System.out.println(input); 
      Reader r = new StringReader(input); 
      CsvReader csv = new CsvReader(r); 
      String s; 
      while((s = csv.next()) != null){ 
       System.out.println("R" + csv.getRowNum() + "C" + csv.getColNum() + ": " + s); 
      } 
     } catch(IOException e){ 
      e.printStackTrace(); 
     } 
    } 
} 

Выполнение этого кода, я получаю выход:

R0C0: apple 
R0C1: boy 
R0C2: cat 
R0C3: dog,cat 
R0C4: time" after"noon 
R1C0: quickfix hello 
R1C1: "who's there? 

Это должно хорошо подходите к вашим потребностям.

Несколько дисклеймеров, хотя:

  • Это не будет перехватывать ошибки в синтаксисе формата CSV, такие как немаскированная кавычка в середине значения.
  • Он не будет выполнять преобразования символов (например, преобразование «\ n» в символ новой строки).Обратные слэши просто приводят к тому, что следующий символ обрабатывается буквально, включая другие обратные косые черты. (Это должно быть достаточно легко изменить, если вам нужна дополнительная функциональность)
  • Некоторые файлы csv сбрасывают кавычки, удваивая их, а не используя обратную косую черту, этот код теперь ищет оба.

Редактировать: просмотрел формат csv, обнаружил, что нет никакого реального стандарта, но обновил мой код, чтобы выловить цитаты, спрятанные удвоением, а не обратной косой чертой.

Редактировать 2: Исправлено. Должна работать как рекламируемая сейчас. Также изменили его, чтобы проверить отслеживание номеров строк и столбцов.

+0

На самом деле есть стандарт: [RFC 4180] (http://tools.ietf.org/html/rfc4180), но он указывает старое цитирование в стиле Microsoft, означающее, что котировки в значении удваиваются, а не сбрасываются с помощью обратного слэша. – VGR

+0

Я думаю, что это не сработает, если у вас есть строка ввода: «r \\ at, ze \\ \ "bra, \" собака, кошка \ ", \" животное, муравей, лиса, дом ", я пробовал делать s ame, если у меня есть двойная кавычка в начале строки, которую она не закрывает, мы не можем решить ее. – user1272855

+0

Двойная цитата, выполняемая только внутри пары котировок. "" - пустая строка. «» «« разрешалось ». Я тестировал каждую вариацию, о которой я могу думать, и она решает то, что я ожидаю. –

0

Первое: String.split() использует регулярное выражение для поиска разделителей, а не подстрок.

Редактировать: Я не уверен, что это можно сделать с помощью String.split(). Я думаю, что единственный способ, которым вы могли бы справиться с кавычками, в то время как только совпадение с запятой было бы с помощью readahead и lookbehind, и это сильно сломается во многих случаях.

Edit2: Я уверен, что это можно сделать с помощью регулярного выражения. И я уверен, что этот один случай можно решить с помощью string.split() - но общее решение не будет простым.

В принципе, вы ищете что-либо, что не является запятой в качестве входных данных [^,], вы можете обрабатывать кавычки как отдельный символ. Я сам проделал большую часть работы. Я получаю это как вывод:

apple 

boy 

cat 


dog 

cat 



time\" after\"noon 

Но я не уверен, почему у него так много пустых строк.

Мой полный код:

String input = "apple,boy,cat,\"dog,cat\",\"time\\\" after\\\"noon\""; 

Pattern pattern = 
     Pattern.compile("(\\s|[^,\"\\\\]|(\\\\.)||(\".*\"))*"); 
Matcher m = pattern.matcher(input); 

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

Но да, я эхо парень выше и сказать, что, если нет никакого требования, чтобы использовать регулярные выражения, то это, вероятно, проще сделать это вручную.

Но тогда я думаю, что я почти там. Это выплевывает ... о, эй, я вижу, что здесь происходит. Думаю, я могу это исправить.

Но я собираюсь повторить парня выше и сказать, что если нет требования использовать регулярное выражение, вероятно, лучше сделать это по одному символу за раз и реализовать логику вручную. Если ваше регулярное выражение не идеальное изображение, это может привести к возникновению всех видов непредсказуемой странности.

+0

Я работаю с файлами csv и множеством данных в этом .... проблема в том, что для того, чтобы иметь a (запятую) как часть строковой оценки е. они имеют двойные кавычки, например, для слова «кошка», мальчик, они пишут его как «кошка, мальчик» и печатают «в этом случае они ускользают от него. Спасибо заранее и спасибо за ответы и предложения – user1272855

+0

Я собираюсь добавить альтернативное решение ниже, так как нет требования к регулярному выражению. Я не собираюсь находить хорошее регулярное выражение для этого. Обработка обратных косых черт оказывается очень сложной. –

+0

Большое спасибо за ответы, без регулярного выражения она отлично работала для меня спасибо за помощь и предложения :) – user1272855

0

Я не совсем уверен в этом, но вы могли бы пойти на Pattern.compile("[\\\\"]");

\ является экранирующим символом и обнаружить в выражении в \, \\\\ может быть использован.

Аналогичная вещь работала для меня в another context, и я надеюсь, что она решает и вашу проблему.

+0

Я боюсь, проблема с OPs лежит глубже, чем в \ literal в regex. – Pshemo

+0

Да, я понимаю, что его проблема заключается в том, более сильная ошибка, и это мало помогло бы ему, но я полагаю, что это могло бы помочь ему обнаружить '\\' в выражении. – Swayam

Смежные вопросы