Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / Delphi Новый топик    Ответить
 TRegExpr, csv  [new]
aford
Member

Откуда:
Сообщений: 52
Всем привет! Знаю, что парсить CSV файлы регулярными выражениями не есть хорошая идея, но очень надо.

Выражение
автор
RegExp.Expression := '(,|,\s)*?(.*?)(,|$)';


Строка
автор
value 1, value 3
value 4, value 5, value 6


Результат
автор
value 1
value 3

value 4
value 5
value 6


Все устраивает, но в csv бывают строки вида "sas (ыфыф, sasas,)" и парсер ломается. Изъезженная тема, но готового решения я пока не нашел. Как мне сделать, чтобы в тексте
автор
value 1,sasasas (sasas,sasas sas,s s, asasas), value 3
value 4, value 5, value 6

Программа отрабатывала не так
автор
value 1
sasasas (sasas
sasas sas
s s
asasas)
value 3

value 4
value 5
value 6


а вот так?
автор
value 1
sasasas (sasas,sasas sas,s s, asasas)
value 3
value 4
value 5
value 6
29 ноя 18, 12:21    [21748390]     Ответить | Цитировать Сообщить модератору
 Re: TRegExpr, csv  [new]
alekcvp
Member

Откуда:
Сообщений: 1205
aford,

ИМХО тут реально лучше конечный автомат использовать, потому что для RegExp в этом случае потребутся lookbehind конструкции, а они а) не всеми движками поддерживаются и б) медленные.
29 ноя 18, 12:57    [21748440]     Ответить | Цитировать Сообщить модератору
 Re: TRegExpr, csv  [new]
alekcvp
Member

Откуда:
Сообщений: 1205
+ Там и код-то элементарный, чтобы с RegEx заморачиваться
type
  TOnValue = procedure (const Value: string);

procedure SplitValues(Source: PChar; OnValue: TOnValue);

  procedure DoValue(VLen: Integer);
  var
    Value: string;
  begin
    SetString(Value, Source, VLen);
    OnValue(Value);
    Inc(Source, VLen + 1);
  end;

var
  Cursor: PChar;
  Skip: Integer;
begin
  Skip := 0;
  Cursor := Source;
  repeat
    case Cursor^ of
      #0: Break;
      '(': Inc(Skip);
      ')': if Skip > 0 then
             Dec(Skip);
      ',', #13, #10:
        if Skip = 0 then
        begin
          DoValue(Cursor - Source);
          if Source^ in [#9, #10, #13, #32] then
            Inc(Source);
          Cursor := Source;
        end;
    end;
    Inc(Cursor);
  until False;
  if Cursor > Source then
    DoValue(Cursor - Source);
end;


var
  TestValues: string =
    'value 1,sasasas (sasas,sasas sas,s s, asasas), value 3' + sLineBreak +
    'value 4, value 5, value 6';

procedure OnValue(const Value: string);
begin
  WriteLn('Value: ' + Value);
end;

begin
  SplitValues(PChar(TestValues), OnValue);
  ReadLn;
end.
 
29 ноя 18, 13:30    [21748498]     Ответить | Цитировать Сообщить модератору
 Re: TRegExpr, csv  [new]
aford
Member

Откуда:
Сообщений: 52
alekcvp,
спасибо, но нужно использовать именно regexpr(
Неужели ничего не придумали? Перерыл кучу регулярных выражений с форумов, но с TRegExpr вылезают ошибки.
Единственное верное решение костыль, которое я сейчас вижу - обрабатывать текст и заменять запятые в кавычках на какие-либо еще символы, а потом обратно после обработки выражением
29 ноя 18, 14:04    [21748568]     Ответить | Цитировать Сообщить модератору
 Re: TRegExpr, csv  [new]
alekcvp
Member

Откуда:
Сообщений: 1205
aford
alekcvp,
спасибо, но нужно использовать именно regexpr(

А мы, вятские, робяты хватские: и часы могем, да топор не влазит (С)
29 ноя 18, 14:47    [21748651]     Ответить | Цитировать Сообщить модератору
 Re: TRegExpr, csv  [new]
Василий 2
Member

Откуда:
Сообщений: 309
aford
в csv бывают строки вида "sas (ыфыф, sasas,)" и парсер ломается

Вообще правильно он ломается, т.к. это неформат. Строки, содержащие сепаратор, должны закавычиваться.
29 ноя 18, 15:32    [21748745]     Ответить | Цитировать Сообщить модератору
 Re: TRegExpr, csv  [new]
alekcvp
Member

Откуда:
Сообщений: 1205
Василий 2
aford
в csv бывают строки вида "sas (ыфыф, sasas,)" и парсер ломается

Вообще правильно он ломается, т.к. это неформат. Строки, содержащие сепаратор, должны закавычиваться.

Суть в том, что он обрабатывает RegExp'ом. Замени скобки на кавычки - ничего не поменяется.
29 ноя 18, 18:05    [21748953]     Ответить | Цитировать Сообщить модератору
 Re: TRegExpr, csv  [new]
Василий 2
Member

Откуда:
Сообщений: 309
alekcvp
Суть в том, что он обрабатывает RegExp'ом. Замени скобки на кавычки - ничего не поменяется.

Да нет. Если б был формат - можно как-то извращенски с регэскпом попробовать, хотя бы для частного случая (без экранирования кавычек). А сейчас даже КА не поможет (если, конечно, у него не собственный формат - но тогда это и не CSV). В последнем случае достаточно просто добавить группу "\(.*\)". Но опять же это сработает только для частного случая, и всегда можно будет найти вариант, который поломает этот RE
29 ноя 18, 19:36    [21749046]     Ответить | Цитировать Сообщить модератору
 Re: TRegExpr, csv  [new]
alekcvp
Member

Откуда:
Сообщений: 1205
Василий 2
Но опять же это сработает только для частного случая, и всегда можно будет найти вариант, который поломает этот RE
Именно поэтому там нужен собственный парсер, т.к. regexp - это всё-таки немного про другое.
29 ноя 18, 20:05    [21749077]     Ответить | Цитировать Сообщить модератору
 Re: TRegExpr, csv  [new]
Гирлионайльдо
Member

Откуда:
Сообщений: 318
Мне не жалко, держи [^(,]+(?:\([^)]+\)){0,2}[^),]*

Пример работы https://regex101.com/r/bF5wT0/4
30 ноя 18, 02:29    [21749288]     Ответить | Цитировать Сообщить модератору
 Re: TRegExpr, csv  [new]
Гирлионайльдо
Member

Откуда:
Сообщений: 318
Там ещё много есть примеров с использованием рекурсии.

А данный партерн легко и такое распарсит

1997,Ford,E350,"ac, abs, moon",3000.00
1999,Chevy,"Venture «Extended Edition»","",4900.00
1996,Jeep,Grand Cherokee,"MUST SELL! air, moon roof, loaded",4799.00
30 ноя 18, 02:30    [21749289]     Ответить | Цитировать Сообщить модератору
 Re: TRegExpr, csv  [new]
aford
Member

Откуда:
Сообщений: 52
Гирлионайльдо,
Спасибо!
30 ноя 18, 08:33    [21749363]     Ответить | Цитировать Сообщить модератору
 Re: TRegExpr, csv  [new]
aford
Member

Откуда:
Сообщений: 52
Гирлионайльдо,
А если не поломанный csv?
Вот так не срабатывает
автор
[^",]+(?:\"[^"]+\"){0,2}[^",]*
30 ноя 18, 08:36    [21749366]     Ответить | Цитировать Сообщить модератору
 Re: TRegExpr, csv  [new]
zinpub
Member

Откуда:
Сообщений: 296
Гирлионайльдо
Мне не жалко, держи [^(,]+(?:\([^)]+\)){0,2}[^),]*

Пример работы https://regex101.com/r/bF5wT0/4


Красиво! Но... если

К сообщению приложен файл. Размер - 2Kb
30 ноя 18, 08:42    [21749371]     Ответить | Цитировать Сообщить модератору
 Re: TRegExpr, csv  [new]
Гирлионайльдо
Member

Откуда:
Сообщений: 318
aford,

Да. Забыл добавить перенос.


Если сломанный, то вот так

https://regex101.com/r/bF5wT0/5

value 1,sasasas (sasas,sasas sas,s s, (htrth) asasas,), value 3

value 4, value 5, value 6


1997,Ford,E350,"ac, abs, moon",3000.00
1999,Chevy,"Venture «Extended Edition»","",4900.00
1996,Jeep,Grand Cherokee,"MUST SELL! air, moon roof, loaded",4799.00 


Даёт такой ответ

matchgroupis_participatingstartendcontent 10yes018zend_mm_heap *heap 11yeszend_mm_heap *heap 20yes1944 void* (*_malloc)(size_t) 21yes void* (*_malloc)(size_t) 30yes4566void (*_free)(void*) 31yesvoid (*_free)(void*) 40yes67100" void* (*_realloc)(void* size_t)" 41yes" void* (*_realloc)(void* size_t)"
30 ноя 18, 10:31    [21749529]     Ответить | Цитировать Сообщить модератору
 Re: TRegExpr, csv  [new]
Гирлионайльдо
Member

Откуда:
Сообщений: 318
matchgroupis_participatingstartendcontent
10yes07value 1
11no-1-1
12yes07value 1
20yes854"sasasas (sasassasas sass s (htrth) asasas)"
21yes854"sasasas (sasassasas sass s (htrth) asasas)"
30yes5563 value 3
31no-1-1
32yes5563 value 3
40yes6572value 4
41no-1-1
42yes6572value 4
50yes7381 value 5
51no-1-1
52yes7381 value 5
60yes8290 value 6
61no-1-1
62yes8290 value 6
70yes93971997
71no-1-1
72yes93971997
80yes98102Ford
81no-1-1
82yes98102Ford
90yes103107E350
91no-1-1
92yes103107E350
100yes108111"ac
101no-1-1
102yes108111"ac
110yes112116 abs
111no-1-1
112yes112116 abs
120yes117123 moon"
121no-1-1
122yes117123 moon"
130yes1241313000.00
131no-1-1
132yes1241313000.00
140yes1321361999
141no-1-1
142yes1321361999
150yes137142Chevy
151no-1-1
152yes137142Chevy
160yes143171"Venture «Extended Edition»"
161no-1-1
162yes143171"Venture «Extended Edition»"
170yes172174""
171no-1-1
172yes172174""
180yes1751824900.00
181no-1-1
182yes1751824900.00
190yes1831871996
191no-1-1
192yes1831871996
200yes188192Jeep
201no-1-1
202yes188192Jeep
210yes193207Grand Cherokee
211no-1-1
212yes193207Grand Cherokee
220yes208223"MUST SELL! air
221no-1-1
222yes208223"MUST SELL! air
230yes224234 moon roof
231no-1-1
232yes224234 moon roof
240yes235243 loaded"
241no-1-1
242yes235243 loaded"
250yes2442524799.00
251no-1-1
252yes2442524799.00
30 ноя 18, 10:34    [21749533]     Ответить | Цитировать Сообщить модератору
 Re: TRegExpr, csv  [new]
Василий 2
Member

Откуда:
Сообщений: 309
alekcvp
Именно поэтому там нужен собственный парсер, т.к. regexp - это всё-таки немного про другое.

ТС-у нужен именно RE, он это осознанно подтвердил. Поэтому разговоры про то, что это не труЪ, что нужен парсер, и прочие КГ/АМ - бесполезны и оффтоп. Имхо
30 ноя 18, 10:54    [21749590]     Ответить | Цитировать Сообщить модератору
 Re: TRegExpr, csv  [new]
alekcvp
Member

Откуда:
Сообщений: 1205
Гирлионайльдо
aford,

Да. Забыл добавить перенос.

Если сломанный, то вот так

https://regex101.com/r/bF5wT0/5

Продолжаем развлекаться :)
Картинка с другого сайта.
30 ноя 18, 11:22    [21749672]     Ответить | Цитировать Сообщить модератору
 Re: TRegExpr, csv  [new]
alekcvp
Member

Откуда:
Сообщений: 1205
Василий 2
alekcvp
Именно поэтому там нужен собственный парсер, т.к. regexp - это всё-таки немного про другое.

ТС-у нужен именно RE, он это осознанно подтвердил. Поэтому разговоры про то, что это не труЪ, что нужен парсер, и прочие КГ/АМ - бесполезны и оффтоп. Имхо

Ну да бесполезны. Клиент хочет выкопать котлован под дачный дом при помощи снегоуборочной машины, ничего не поделаешь, придётся копать :)
30 ноя 18, 11:24    [21749677]     Ответить | Цитировать Сообщить модератору
 Re: TRegExpr, csv  [new]
Гирлионайльдо
Member

Откуда:
Сообщений: 318
alekcvp,

Врать не нужно.

Но скобки можно и убрать "/[^,]+\((?:[^()]{0,}|(?R))*\)|[^(,\n]+/g"

К сообщению приложен файл. Размер - 16Kb
30 ноя 18, 13:44    [21749936]     Ответить | Цитировать Сообщить модератору
 Re: TRegExpr, csv  [new]
alekcvp
Member

Откуда:
Сообщений: 1205
Гирлионайльдо
alekcvp,
Врать не нужно.

Где я вру? Я показал пример данных, на котором твой регекс не работает. Можешь гарантировать, что такого сочетания в исходных данных никогда не появится?..

Картинка с другого сайта.
30 ноя 18, 19:29    [21750702]     Ответить | Цитировать Сообщить модератору
Все форумы / Delphi Ответить