Регулярное выражение для csv с запятыми и без кавычек

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

Jake,HomePC,Microsoft VS2010, Microsoft Office 2010

Должен быть проанализирован до

Jake
HomePC
Microsoft VS2010, Microsoft Office 2010

Кто-нибудь может посоветовать, как включить "\s" и "\s" в тело столбца.


person Johnny_D    schedule 13.07.2012    source источник
comment
Возможно, разделить на ,(?!\s)(?<!\s)?   -  person Wrikken    schedule 13.07.2012
comment
@Wrikken, не так хорош в регулярных выражениях, не могли бы вы привести пример использования. Спасибо.   -  person Johnny_D    schedule 13.07.2012
comment
Это явно не файл CSV, если он не экранирует данные правильно. Если это вообще возможно, я бы получил данные для создания правильно отформатированного CSV-файла   -  person Brad    schedule 13.07.2012
comment
@Брэд, у меня нет возможности измениться, мне приходится работать с тем, что я получаю   -  person Johnny_D    schedule 13.07.2012
comment
@Wrikken, кажется, твой совет помог, можешь написать как ответ, чтобы я мог его отметить.   -  person Johnny_D    schedule 13.07.2012
comment
@Wrikken, вам также нужно проверить наличие пробелов перед .   -  person sarveshseri    schedule 13.07.2012
comment
@Brad - ну ... файл содержит значения, и, правильно отформатированные, разборчивые или нет, эти значения разделены запятыми - верно? разве это не сделает его файлом значений, разделенных запятыми (или файлом CSV)? возможно, где-то есть стандарт ISO, определяющий CSV, о котором я не знаю?   -  person Code Jockey    schedule 13.07.2012
comment
@CodeJockey см. ссылку на Википедию в моем комментарии и, в частности, раздел «Основные правила и примеры», где упоминаются поля со встроенными запятыми, которые должны быть заключены в кавычки. Любой, кто имел дело с плохо продуманным, доморощенным форматом файлов, таким как бедный Johnny_D здесь, знает боль   -  person Brad    schedule 13.07.2012
comment
@Brad. Моя точка зрения изложена в отсутствии стандартного раздела этого та же самая статья - хоть и есть RFC (и несколько других рекомендаций), стандарта нет - я не говорю, что он не в плохой ситуации, или что было бы неразумно настаивать на правильно отформатированных исходных данных - - потому что было бы глупо полагаться на игнорирование запятых, за которыми следуют пробелы для разделения данных. Просто он на самом деле имеет дело со значениями, разделенными запятыми, хранящимися в файле — таким образом, CSV не является неточным.   -  person Code Jockey    schedule 13.07.2012
comment
@SarveshKumarSingh: Ах, я потерял (?<!\s), я вижу, выбежал из двери на работу, когда опубликовал это :)   -  person Wrikken    schedule 13.07.2012


Ответы (3)


Если ваш язык поддерживает проверки назад, разделите их на

(?<!\s),(?!\s)

In C#:

string[] splitArray = Regex.Split(subjectString, 
    @"(?<!\s) # Assert that the previous character isn't whitespace
    ,         # Match a comma
    (?!\s)    # Assert that the following character isn't whitespace", 
    RegexOptions.IgnorePatternWhitespace);
person Tim Pietzcker    schedule 13.07.2012
comment
Да, просто не забудьте поместить регулярное выражение в дословную строку (@"..."). - person Tim Pietzcker; 13.07.2012

разделить на r"(?!\s+),(?!\s+)"

в питоне вы можете сделать это так

import re
re.split(r"(?!\s+),(?!\s+)", s) # s is your string
person sarveshseri    schedule 13.07.2012
comment
Это неправильно и неэлегантно. Вам нужно ретроспективное утверждение, и вам не нужны квантификаторы. - person Tim Pietzcker; 13.07.2012

Попробуй это. Это дало мне желаемый результат, о котором вы упомянули.

StringBuilder testt = new StringBuilder("Jake,HomePC,Microsoft VS2010, Microsoft Office 2010,Microsoft VS2010, Microsoft Office 2010");
Pattern varPattern = Pattern.compile("[a-z0-9],[a-z0-9]", Pattern.CASE_INSENSITIVE);
Matcher varMatcher = varPattern.matcher(testt);
List<String> list = new ArrayList<String>();
int startIndex = 0, endIndex = 0;
boolean found = false;
while (varMatcher.find()) {
endIndex = varMatcher.start()+1;
if (startIndex == 0) {
list.add(testt.substring(startIndex, endIndex));
} else {
startIndex++;
list.add(testt.substring(startIndex, endIndex));
}
startIndex = endIndex;
found = true;
}
if (found) {
if (startIndex == 0) {
list.add(testt.substring(startIndex));
} else {
list.add(testt.substring(startIndex + 1));
}
}
for (String s : list) {
System.out.println(s);
}

Обратите внимание, что код написан на Java.

person Saurabh    schedule 13.07.2012