Regex para juntar campos em um CSV

Regex para juntar campos em um CSV

Eu tenho um CSV com mais de 2 milhões de registros com o seguinte formato.

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

Preciso juntar o caminho, nome e extensão em um campo formatado corretamente.

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

Desde já, obrigado!

Responder1

Esta é uma variação da resposta do slhck que lida adequadamente com um campo de extensão vazio (e evita a substituição falsa de um ponto que pode ter existido intencionalmente no segundo ou terceiro campo):

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

Não é necessário utilizar um terceiro grupo de captura. Essa resposta funciona sem ele. Não é necessário escapar do ponto à direita do comando substituto.

Aqui está uma explicação do meu script:

  • capture os dois primeiros campos, excluindo os pontos e vírgulas que os delimitam.
  • ta;:a- se uma substituição bem-sucedida foi feita, então ramifique para o rótulo :aque segue imediatamente - isso efetivamente limpa o sinalizador de "sucesso"
  • s/^[^;]\+;;/&/- substitua uma sequência de não-ponto-e-vírgula seguida por dois ponto-e-vírgula (o primeiro e o segundo campos concatenados seguidos por um terceiro campo vazio) por ela mesma - é autônomo, mas define o sinalizador de "sucesso".
  • t- se a última substituição foi bem-sucedida (o terceiro campo está vazio), pule para o final do processamento da linha atual (já que nenhum rótulo foi especificado)
  • s/;/./- se chegamos a este ponto (o terceiro campo foinãovazio), substitua o ponto e vírgula por um ponto.

informação relacionada