Junte-se a vários comandos sed em um script para processar o arquivo CSV

34

Ter um arquivo CSV como este:

HEADER
"first, column"|"second "some random quotes" column"|"third ol' column"
FOOTER

e procurando resultados como:

HEADER
first, column|second "some random quotes" column|third ol' column

por outras palavras, remover "FOOTER", aspas no início, fim e à volta |.

Até agora, esse código funciona:

sed '/FOOTER/d' csv > csv1 | #remove FOOTER
sed 's/^\"//' csv1 > csv2 | #remove quote at the beginning
sed 's/\"$//' csv2 > csv3 | #remove quote at the end
sed 's/\"|\"/|/g' csv3 > csv4 #remove quotes around pipe

Como você vê, o problema é que ele cria 4 arquivos extras.

Aqui está outra solução, que tem como objetivo não criar arquivos extras e fazer a mesma coisa em um único script. Não funciona muito bem.

#!/bin/ksh

sed '/begin/, /end/ { 
        /FOOTER/d
        s/^\"//
        s/\"$//
        s/\"|\"/|/g 
}' csv > csv4
Bor
fonte
1
Como você está cotando, pode ter novas linhas nos campos. você sednão vai trabalhar com isso, apenas com CSV simplificado. Use uma linguagem de programação com uma biblioteca que possa lidar com arquivos CSV reais (Python / Perl / Ruby).
Anthon

Respostas:

44

Antes de tudo, como Michael mostrou, você pode simplesmente combinar tudo isso em um único comando:

sed '/^FOOTER/d; s/^\"//; s/\"$//; s/\"|\"/|/g' csv > csv1

Eu acho que algumas sedimplementações não conseguem lidar com isso e podem precisar de:

  sed -e '/^FOOTER/d' -e 's/^\"//' -e 's/\"$//' -e 's/\"|\"/|/g' csv > csv1

Dito isso, parece que seus campos são definidos |e você deseja apenas remover "todo o campo, deixando aqueles que estão dentro do campo. Nesse caso, você pode fazer:

$ sed '/FOOTER/d; s/\(^\||\)"/\1/g; s/"\($\||\)/\1/g' csv 
HEADER
first, column|second "some random quotes" column|third ol' column

Ou, com o GNU sed:

sed -r '/FOOTER/d; s/(^|\|)"/\1/g; s/"($|\|)/\1/g' csv 

Você também pode usar o Perl:

$ perl -F"|" -lane 'next if /FOOTER/; s/^"|"$// for @F; print @F' csv 
HEADER
first, column|second some random quotes column|third ol' column
terdon
fonte
13

Isso também funcionaria:

sed 's / ^ "//; s /" | "/ | / g; s /" "$ /" /'

Exemplo:

$ echo '"this"|" and "ths""|" and "|" this 2"|" also "this", "thi", "and th""' | 
sed 's/^"//; s/"|"/|/g; s/""$/"/'
this| and "ths"| and | this 2| also "this", "thi", "and th"

versão bonita

sed '
s/^"//
s/"|"/|/g
s/""$/"/
$d
'
Michael Durrant
fonte
1
Isso não lida com o rodapé.
terdon
3
Mas isso removerá a última linha, independentemente do seu conteúdo. Se não houver FOOTER, ele removerá os dados desejados.
terdon