Регулярное выражение для объединения полей в CSV

Регулярное выражение для объединения полей в CSV

У меня есть CSV-файл с более чем 2 миллионами записей в следующем формате.

path;name;extension;size;date;user    
/foo/;difacs;cgi;3,795;18-07-2011;Unix User\pads
/foo/;difacs.cgi;bak;2,622;03-12-2009;Unix User\pads
/foo/test/kzt/netcdfSample/testing/;zzz;;401;27-07-2006;Unix User\kzt
/foo/test/kzt/netcdfSample/vic_netcdf_popup/;a;txt;1,832;17-02-2006;Unix User\kzt

Мне нужно объединить путь, имя и расширение в одно правильно отформатированное поле.

path;size;date;user    
/foo/difacs.cgi;3,795;18-07-2011;Unix User\pads
/foo/difacs.cgi;bak;2,622;03-12-2009;Unix User\pads
/foo/test/kzt/netcdfSample/testing/zzz/;401;27-07-2006;Unix User\kzt
/foo/test/kzt/netcdfSample/vic_netcdf_popup/a.txt;1,832;17-02-2006;Unix User\kzt

Заранее спасибо!

решение1

Это вариация ответа slhck, которая правильно обрабатывает пустое поле расширения (и избегает ложной замены точки, которая могла намеренно существовать во втором или третьем поле):

sed 's/^\([^;]*\);\([^;]*\)/\1\2/;ta;:a;s/^[^;]\+;;/&/;t;s/;/./' inputfile

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

Вот объяснение моего сценария:

  • захватите первые два поля, за исключением точек с запятой, которые их разделяют.
  • ta;:a- если замена прошла успешно, то переходим к метке, :aкоторая следует сразу за ней - это фактически снимает флаг "успешно"
  • s/^[^;]\+;;/&/- заменить последовательность не-точек с запятой, за которой следуют две точки с запятой (объединенные первое и второе поля, за которыми следует пустое третье поле) на себя — это пустая операция, но она устанавливает флаг «успешно».
  • t- если последняя замена прошла успешно (третье поле пустое), перейти к концу обработки текущей строки (так как метка не указана)
  • s/;/./- если мы дошли до этой точки (третье поле былонетпусто), замените точку с запятой на точку.

Связанный контент