1

У меня есть 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 ответ1

1

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

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

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

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

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

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .