[Bash - if] Explication de fonctionnement

Tags: #<Tag:0x00007f8a47f3e520>

Bonjour à toutes et à tous,

J’ai fait une petite boucle très simple qui ne fonctionnait pas :

    if [ $i = $db ] && [ $i = information_schema ] && [  $i = performance_schema ]
    then
           echo "passe"
    else 
             sudo mysqldump -d $i > $DIR_BCK/$i-`date +%d%m%Y`
    fi

je me suis cassé la tête jusqu’à intervertir la condition

if [ $i != $db ] && [ $i != information_schema ] && [ $i != performance_schema ]
    then
    sudo mysqldump -d $i > $DIR_BCK/$i-`date +%d%m%Y`
else 
    echo "pass"
fi

et ça marche… mais pourquoi ?? :thinking:

merci pour votre réponse et bonne journée !

Parce-que les conditions ne sont pas remplies, jusqu’à preuve du contraire.

Exemple:
[ $i = information_schema ] && [ $i = performance_schema ]

Impossible.

salut
déjà nous dire ce que tu veux qu’elle fasse.
ensuite le la comparaison se fait avec == pas =
de plus on ne peut pas avoir $i égal à trois trucs différents ( il faudrait un OU ) : if [ $i == $db ] || [ $i == information_schema ] || [ $i == performance_schema ]
metrte des guillemets autour de $i : "$i"

Merci pour vos réponses, je suis tout à fait d’accord avec ce que vous avez noté.

ce genre de kernel panic cérébral me revient lorsque je refais du bash après de longs mois d’inactivité.

Navré du désagrément, tout est « normal ».

[ $i != $db ] && [ $i != information_schema ] && [ $i != performance_schema ]

est largement satisfaite, le but ayant été d’exclure les bases susnommées, de sauvegarder le reste, ce qui est un succès.

Merci à vous et bonne soirée !

Merci Dindoun,

ce sont les syntaxes comparatives qui me crées un brain storm. J’avais eu une erreur de syntaxe avec le if, que je ne comprends toujours pas ; ça a été résolu avec la ligne que tu lis au-dessus (oui, il n y a qu’un seul = … )
Je n’arrive pas à comprendre la distnction avec d’autres sites qui proposent le == et d’autres le = mais… ça marche. :exploding_head:

Merci et bonne soirée !

La syntaxe entre [ ou [[, et = ou == diffère selon que exécutes un script en dash ou bash.
Le dash correspond à sh dans Debian, dash étant le script système de base par défaut.

readlink /usr/bin/sh
dash

La syntaxe en dash sera plus portable « [,= », mais n’a pas la puissance de la syntaxe de bash5.

1 J'aime

Merci pour ces explications O_o

D’où l’importance de shabang.

Bonne soirée !

C’est une simple question de logique :

!a AND !b AND !c ≠ !(a AND b AND c)

Là, tu n’as pas « interverti la condition », tu l’as juste modifiée.
C’est pour ça et aussi parce que

ça marche parce que

if [ $i = $db ] && [ $i = information_schema ] && [  $i = performance_schema ]

n’est pas la négation de

if [ $i != $db ] && [ $i != information_schema ] && [ $i != performance_schema ]

En logique, la négation de (P et Q) est non(P) OU non(Q).

donc ici la première condition aurez dû être :

if [ $i = $db ] || [ $i = information_schema ] || [  $i = performance_schema ]

D’ailleurs, $i ne peut pas avoir 3 valeurs différentes en même temps :wink: (Ou alors peut-être en Informatique Quantique…)

Cordialement,

C’est comme dans « être ou ne pas être ». On ne peut « être et ne pas être », je pense que a_O a compris…
Le plus intéressant est la différence de syntaxe entre dash et bash, qui n’est pas évidente et parfois confuse, selon les versions de bash.

Sinon, en plus compact, en bash:

[[ $i =~ $db|information_schema|performance_schema ]] && echo OK || echo KO

i=x ; db=x => OK
i=x ; db=y => KO

1 J'aime

Bonjour,

Merci pour vos réponses !

Effectivement, nous ne sommes pas (encore) en informatique Quantique et il ne s’agit pas (encore) de chat mort ET OU vivants :stuck_out_tongue:

J’avais eu un moment d’absence, il s’agit ici d’un ET inclusif et non d’exclusion…

Merci encore et bonne journée !

Oui @Verner , c’est cela qui est intéressant et que j’ignorais en grande parti.
Je savais que parfois il fallait spécifier le shell /bin/bash à la place de /bin/sh mais sans forcément réellement savoir pourquoi… toute cette histoire de syntaxe est beaucoup plus confuse qu’on ne le pense ; si on ignore les réelles différences…

D’autant que je viens d’apprendre que Bash n’est plus POSIX ??? O_o

as-tu un lien explicatif et plus ou moins exhaustif là-dessus ?

Merci et bonne journée :slight_smile:

Par défaut non, mais pourtant…
Mode POSIX de Bash - Démarrer Bash avec --posixoption de ligne de commande

Pour moi POSIX veut dire ‹ portable ›, sans ambiguïté pour le système.
La référence script POSIX pour Debian est le dash.
Si ça marche avec dash, on est sûr qu’il n’y pas d’embrouilles, et que bash ou zsh comprendront la syntaxe.
Pour des scripts plus compliqués, bash est quand-même plus confortable et plus puissant.

Pour être franc, c’est un sujet hyper prise de tête. Il y a une tonne de documentations bash, qui créent la confusion puisqu’il est facile de trouver des contradictions d’une version à l’autre, selon l’ancienneté des versions.
Je suis toujours très prudent sur le sujet…

Merci @Verner pour ces précisions, je comprends beaucoup mieux certains problèmes que j’ai pu rencontrer dans le passé.
Et surtout sur, parfois, mon incompréhension et mon désespoir sur le « pourquoi cette syntaxe et pas l’autre qui marchait pourtant ?? ».

Merci pour le lie qui parait être une mine de code :smiley: et bon dimanche :slight_smile:

ça marche peut-être, mais c’est toujours aussi casse-tête.
Pour la simple raison que vous n’avez pas choisi la syntaxe adaptée. Dans votre cas vous voulez faire un traitement différencié pour un certain nombre de cas possibles selon la valeur d’une variable $i (que vous deviez mettre entre " ).

La bonne structure syntaxique dans votre cas est case :

case "$i" in
   sdb|information_schema|performance_schema)  echo "passe"
      ;;
   *)    sudo mysqldump -d "$i" > "$DIR_BCK"/"$i"-"$(date +%d%m%Y)"
     ;;
esac

(en ajoutant avec grande difficulté des quotes doubles, le widget d’édition et ma vue foireuse, cela fait deux ).
S’il y a plusieurs alternatives pour une variable donnée, utilisez case et surtout raisonnez en logique positive.

Cordialement,
Regards,
Mit freundlichen Grüßen,
مع تحياتي الخالصة


F. Petitjean
Ingénieur civil du Génie Maritime.

« Ce que l’on conçoit bien s’énonce clairement,
Et les mots pour le dire arrivent aisément. »
Boileau De L’Art poétique (Chant I)

1 J'aime

Ou l’art de compliquer inutilement un problème déjà résolu.
‹ case › ne présente pas d’intérêt dans ce cas présent puisque c’est un test binaire: OK ou pas OK.
‹ case › est adapté aux cas multi-options (> 2).
‹ case › n’est pas posix, donc inutile pour un simple test système de préférence compatible dash.

I be to differ
Dans le cas présent, le test binaire (OK ou pas OKà est si compliqué ç formuler que @a_O s’est initialement planté et a été obligé de demander de l’aide.

Comment appelez-vous les différentes alternatives reliées par un ou logique symbolisé par le symbole | dans l’expression régulière du case ? ce n’est pas "multi-options’ pour vous ?

Merci de l’avoir précisé. Je ne le savais pas.

Cordialement,
Regards,
Mit freundlichen Grüßen,
مع تحياتي الخالصة


F. Petitjean
Ingénieur civil du Génie Maritime.

« Je préfère le vin d’ici à l’au-delà »
Pierre Dac

Ce que j’appelle une liste ‹ multi-options › ‹ >2 ›, c’est ça.

case "$i" in 
   x|y) echo A ;;
   z) echo B ;;
   v) echo C ;;
   t) echo D ;;
   # etc etc...
esac

Sinon, ou peut aussi faire avec une liste de if et de ‹ elif ›, qui n’aurait pas non plus d’intérêt pour un simple test OK ou pas OK.

Donc, en non posix et déjà cité, ça c’était pas plus simple et plus compact ?

[[ $i =~ $db|information_schema|performance_schema ]] 

C’est un test regex non posix qui est exactement le même que 'case "$i" in sdb|information_schema|performance_schema)

case n’apporte rien de plus ici.
Pas besoin de 50 messages sur des sujets aussi simples quand-même, la difficulté principale étant de comprendre la différence entre dash et bash, posix et non posix.