Si j'ai un fichier csv, existe-t-il un moyen rapide en bash d'imprimer le contenu d'une seule colonne ? On peut supposer en toute sécurité que chaque ligne a le même nombre de colonnes, mais le contenu de chaque colonne aurait une longueur différente.
Réponses
Trop de publicités?
qneill
Points
347
Utilise ce code depuis un moment, ce n'est pas "rapide" sauf si tu comptes "copier-coller depuis stackoverflow".
Il utilise les opérateurs ${##} et ${%%} dans une boucle au lieu de IFS. Il appelle 'err' et 'die', et ne prend en charge que les caractères de séparation virgule, tiret et barre verticale (c'est tout ce dont j'avais besoin).
err() { echo "${0##*/}: Erreur:" "$@" >&2; }
die() { err "$@"; exit 1; }
# Retourner le N-ième champ dans une chaîne CSV, les champs numérotés à partir de 1
csv_fldN() { fldN , "$1" "$2"; }
# Retourner le N-ième champ dans une chaîne de champs séparés par SEP, les champs numérotés à partir de 1
fldN() {
local me="fldN: "
local sep="$1"
local fldnum="$2"
local vals="$3"
case "$sep" in
-|,|\|) ;;
*) die "$me: arg1 sep: séparateur '$sep' non pris en charge" ;;
esac
case "$fldnum" in
[0-9]*) [ "$fldnum" -gt 0 ] || { err "$me: arg2 fldnum=$fldnum doit être un nombre supérieur ou égal à 0."; return 1; } ;;
*) { err "$me: arg2 fldnum=$fldnum doit être un nombre"; return 1;} ;;
esac
[ -z "$vals" ] && err "$me: arg2 vals manquant: liste de valeurs séparées par '$sep'" && return 1
fldnum=$(($fldnum - 1))
while [ $fldnum -gt 0 ] ; do
vals="${vals#*$sep}"
fldnum=$(($fldnum - 1))
done
echo ${vals%%$sep*}
}
Exemple:
$ CSVLINE="exemple,champs avec espace,champ3"
$ $ for fno in $(seq 3); do echo champ$fno: $(csv_fldN $fno "$CSVLINE"); done
champ1: exemple
champ2: champs avec espace
champ3: champ3
K. Sopheak
Points
17933
- Réponses précédentes
- Plus de réponses