Forum Programmation.shell IFS= et imbrication

Posté par  . Licence CC By‑SA.
Étiquettes : aucune
0
16
jan.
2015

Bonjour,

J'ai un fichier CSV avec des lignes du genre :

AEQF;bla;bli;blu;ju;jo;toto;foo|bar|baz
SEQI;hik;hop;kii;ji;ju;titi;fii|gii|hop

Je souhaite parcourir chaque ligne, mettre chaque champ dans un tableau et traiter le dernier champ de manière particulière en le « splitant » à son tour. Voici le code :

# Boucle sur le tableau "lines", pour chaque élément définition d'un tableau "fields"
for l in "${lines[@]}"
  do
    while IFS=';' read -a fields
    do
      case "${fields[0]}" in
      "AEQF")
        while IFS='|' read -a hostgroups
          do
            for hg in "${hostgroups[@]}"
              do
                echo "HG;ADD;${hg};${hg}";
              done
          done <<< "${fields[7]}"
        echo "HOST;ADD;${fields[2]};${fields[4]};${fields[3]};${fields[6]};${fields[1]};${fields[7]}"
      ;;

      "SEQI")
        echo "HOST;DEL;${fields[2]}"
      ;;

      *)
        echo "Problem!"
      ;;
      esac
    done <<< "$l"
done

Certains se seront peut-être rendu compte qu'en fait je m'efforce de générer un fichier que CLAPI (Centreon Command Line API) pourra importer, à partir de fichiers CSV générés par un outil maison…

Mon problème est que si la valeur d'un champ possède des espaces ça ne fonctionne pas :(

[stef@459ETU1 ]# cat test1
AEQF;bla;bli;blu;ju;jo;toto;foo|bar|baz
SEQI;hik;hop;kii;ji;ju;titi;fii|gii|hop

[stef@459ETU1 ]# cat test2
AEQF;bla bla;bli;blu;ju;jo;toto;foo|bar|baz
SEQI;hik;hop;kii;ji;ju;titi;fii|gii|hop

[stef@459ETU1 ]# ./clapi_import.sh test1
HG;ADD;foo;foo
HG;ADD;bar;bar
HG;ADD;baz;baz
HOST;ADD;bli;ju;blu;toto;bla;foo|bar|baz
HOST;DEL;hop
[stef@459ETU1 ]# ./clapi_import.sh test2
HOST;ADD;;;;;bla;
Problem!
HOST;DEL;hop
[stef@459ETU1 ]#

Au départ, à la place des

while IFS=';' read -a toto
  dodone <<< "$var"

j'avais utilisé des

IFS=';' && fields=($var)

mais le problème est le même.

Une idée ?

Je suis bien entendu ouvert à toute proposition, je ne tiens pas plus que ça à réussir à imbriquer des IFS= :) Donc d'une manière générale, comment doit-on appréhender ces fichiers CSV avec « deux niveaux de séparateurs » en bash (3.2.25) ? En plus à foutre tout ça dans un case, comment dire… je sens que je me fourvoie !

  • # Réponse à moi même

    Posté par  . Évalué à 3.

    J'aurais dû poster le script en entier tiens :/ En fait je me rends compte que le problème est en amont…

    Le fait que j'arrive au cas *) c'est certainement que le problème survient au moment de la création de mon tableau lines :|

    Bon ben vu que c'est le week-end je verrai ça lundi :)

  • # Awk ?

    Posté par  . Évalué à 2.

    Hello,

    si tu ne t'interdis pas Awk, 15 lignes de script pourraient faire l'affaire (enfin, si j'ai bien compris le résultat à atteindre !) :

    #! /usr/bin/awk -f
    
    BEGIN {
        FS=";"
        OFS=";"
    }
    $1 ~ /AEQF/ {
        split($NF, Array, "|");
    
        for (hg in Array)
        {
            print "HOST;ADD", Array[hg], Array[hg]
        }
        print "HOST;ADD",$3,$5,$4,$7,$2,$8
    }
    $1 ~ /SEQI/ {
        print "HOST;DEL",$3
    }

    Chez moi, le script clapi_import.awk donne ça :

    ./clapi_import.awk sample.txt sample2.txt
    HOST;ADD;foo;foo
    HOST;ADD;bar;bar
    HOST;ADD;baz;baz
    HOST;ADD;bli;ju;blu;toto;bla;foo|bar|baz
    HOST;DEL;hop
    HOST;ADD;foo;foo
    HOST;ADD;bar;bar
    HOST;ADD;baz;baz
    HOST;ADD;bli;ju;blu;toto;bla bla;foo|bar|baz
                            #^^^^^^^ L'espace est bien repris
    HOST;DEL;hop

Suivre le flux des commentaires

Note : les commentaires appartiennent à celles et ceux qui les ont postés. Nous n’en sommes pas responsables.