Joignez plusieurs commandes sed dans un script pour le traitement de fichier CSV

34

Avoir un fichier CSV comme ceci:

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

et cherchant un résultat comme:

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

autrement dit, supprimer "FOOTER", les guillemets au début, à la fin et autour de |.

Jusqu'à présent, ce code fonctionne:

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

Comme vous voyez le problème est qu'il crée 4 fichiers supplémentaires.

Voici une autre solution, qui a pour but de ne pas créer de fichiers supplémentaires et de faire la même chose dans un seul script. Ça ne marche pas très bien.

#!/bin/ksh

sed '/begin/, /end/ { 
        /FOOTER/d
        s/^\"//
        s/\"$//
        s/\"|\"/|/g 
}' csv > csv4
Bor
la source
1
Comme vous avez des devis, vous pouvez avoir des nouvelles lignes dans les champs. votre sedne va pas travailler avec cela, seulement avec CSV simplifié. Utilisez un langage de programmation avec une bibliothèque capable de gérer de vrais fichiers CSV (Python / Perl / Ruby).
Anthon

Réponses:

44

Tout d’abord, comme Michael l’a montré, vous pouvez combiner tout cela en une seule commande:

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

Je pense que certaines sedimplémentations ne peuvent pas gérer cela et pourraient nécessiter:

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

Cela dit, il semble que vos champs soient définis par |et que vous souhaitiez simplement les supprimer ", en laissant ceux qui se trouvent dans le champ. Dans ce cas, vous pourriez faire:

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

Ou, avec GNU sed:

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

Vous pouvez aussi utiliser 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
la source
13

Cela fonctionnerait aussi:

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

Exemple:

$ 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"

jolie version

sed '
s/^"//
s/"|"/|/g
s/""$/"/
$d
'
Michael Durrant
la source
1
Cela ne concerne pas le pied de page.
terdon
3
Mais cela supprimera la dernière ligne quel que soit son contenu. S'il n'y en a pas FOOTER, les données recherchées seront supprimées.
terdon