6135 links
  • GuiGui's Show
  • Home
  • Login
  • RSS Feed
  • ATOM Feed
  • Tag cloud
  • Picture wall
  • Daily
Links per page: 20 50 100
 
  • IFS et interprétation d'une variable

    Je souhaite améliorer un script bash existant. Le principal problème est qu'il utilise n fois une même commande genre mysql -u <login> -p<mdp> -B -N. Il n'y a que le -e <ma_requête_SQL> qui change entre chaque commande.

    J'ai justement un argument à changer… dans chaque appel à la commande. Bon, un coup de sed et le travail est fait, mais je me dis que je vais factoriser tout ça.

    Je crée une variable MYSQLCMD='/usr/bin/mysql -B -N -u <login> -p<mdp>' et je remplace toutes les commandes de la forme mysql -u <login> […] -e "ma_requête_SQL> par $MYSQLCMD -e ma_requête_SQL>.

    Je teste… Ça fonctionne partout… sauf à plusieurs endroits du script. L'erreur est : « mon_script.sh: ligne 138: /usr/bin/mysql -B -N -u root -p<CENSURÉ>: Aucun fichier ou dossier de ce type ». On dirait que bash cherche une commande qui se nomme « /usr/bin/mysql -B -N -u root -p<CENSURÉ> » (espaces incluses). La commande /usr/bin/mysql existe, mais pas une commande /usr/bin/mysql -B -N -u root -p<CENSURÉ> puisqu'il s'agit d'un mélange d'une commande, de ses arguments et des valeurs de ses arguments.

    set -x affiche + '/usr/bin/mysql -B -N -u root -p<CENSURÉ>' -e 'SHOW DATABASES;'. On constate que la variable $MYSQLCMD est développée comme un seul tenant… alors que sa valeur est assignée à l'aide de simples quotes, et non de guillemets. Et, surtout, ce comportement se produit uniquement à partir d'un certain endroit dans le script. Dit autrement, un $MYSQLCMD -e ma_requête_SQL> en début ou en milieu de script fonctionne très bien.

    Solution : un bout de code traînait. Un bout de code tout simple :

    IFS='
    '

    Ainsi, le séparateur des champs a été modifié. Sa valeur est passé de espace + tab + line feed à juste line feed (saut de ligne). Évidemment, cela a été fait dans une intention bien précise : itérer sur chaque ligne d'un résultat d'une requête SQL avec une boucle for… Illustration :

    IFS='
    '
    
    for line in $(mysql -B -N -u <login> -p<mdp> -D <base> -e <requête_sql) do
        [travail sur $line]
    done

    Sans la modification du séparateur, la boucle itère sur chaque colonne du résultat au lieu d'itérer sur chaque ligne du résultat.

    Évidemment, bidouiller IFS est une mauvaise pratique. Dans ce contexte-là, on préférera utiliser une boucle while read. ;)

    Virer cette modification du séparateur résout le problème. \o/

    February 19, 2019 at 8:16:14 PM UTC - permalink - http://shaarli.guiguishow.info/?luxvMw
Links per page: 20 50 100
 
Mentions légales identiques à celles de mon blog | CC BY-SA 3.0

Shaarli - The personal, minimalist, super fast, database-free, bookmarking service by the Shaarli community