2010-07-06 3 views
3

Dans quel ordre les expressions test ou [ sont-elles évaluées dans un script bash? Est-ce la même chose que l'ordre dans lequel ils sont écrits? Sont-ils tous évalués?Qu'est-ce que l'ordre d'évaluation de la commande "test" de bash?

Dans l'exemple suivant:

if [ expr1 -a -n expr2 ] 

sera Expr2 être évaluée si expr1 est faux?

+0

L'exemple n'analyse pas dans bash. -a vérifie l'existence d'un fichier, -n recherche l'existence d'une chaîne non nulle. L'exemple entraîne une erreur "trop ​​d'arguments". – BjoernD

+0

Je n'ai rien trouvé à propos de l'ordre d'évaluation dans les pages de manuel de 'bash' ou' test', donc cela semble être dépendant de l'implémentation. Puisque les expressions 'test' ne changent jamais d'état ou ne déclenchent aucune exception, l'ordre d'évaluation et la paresse n'ont pas d'importance. – Philipp

+1

@Bjoern, il analyse bien. Je ne suis pas sûr de ce que vous utilisez, mais ça fonctionne sous CygWin. C'est un style de test plus ancien utilisant '-a' pour faire" et ". – paxdiablo

Répondre

11

Cela fait longtemps que j'ai utilisé cette syntaxe particulière. De nos jours, je préfère:

if [[ expr1 && -n expr2 ]] 

depuis que je sais que ce sont court-circuitées. La page de manuel bash stipule expressément:

Les opérateurs && et || n'évaluent pas expression2 si la valeur de expression1 est suffisante pour déterminer la valeur de retour de l'ensemble de l'expression conditionnelle.

Il ne semble pas clairement d'une façon ou l'autre pour la variante [ et test (en utilisant -a). Cependant, dans le but d'approfondir vos connaissances et le mien (et une indication de la raison pour laquelle l'open source est une bonne chose), je suis allé à la traîne à travers le code source bash.

Il s'avère que c'est et non court-circuité dans ce cas. Les pièces particulières de code sont (compressé un peu pour la lisibilité):

static int or() { 
    int value, v2; 
    value = and(); 
    if (pos < argc && argv[pos][0] == '-' 
     && argv[pos][1] == 'o' && !argv[pos][2]) 
    { 
     advance (0); 
     v2 = or(); 
     return (value || v2); 
    } 
    return (value); 
} 

static int and() { 
    int value, v2; 
    value = term(); 
    if (pos < argc && argv[pos][0] == '-' 
     && argv[pos][1] == 'a' && !argv[pos][2]) 
    { 
     advance (0); 
     v2 = and(); 
     return (value && v2); 
    } 
    return (value); 
} 

Vous pouvez voir dans ces deux cas, qu'il continue d'interpréter les expressions quel que soit l'état de la première expression.

C'était à partir de bash 2.5 mais je viens de vérifier la source 4.1 et elle n'a pas changé. La source a été tirée directement à partir du horse's mouth.

Donc. ligne du bas: il semble que toutes les sous-expressions sont évaluées en utilisant -a et -o avec test ou [.

+1

Holy ... bash! Vous êtes doué :) – Tom

Questions connexes