792 votes

Comment utiliser les crochets doubles ou simples, les parenthèses et les accolades ?

Je ne sais pas comment utiliser les crochets, les parenthèses et les accolades dans Bash, ni quelle est la différence entre leur forme double ou simple. Existe-t-il une explication claire ?

709voto

Dennis Williamson Points 105818

Dans Bash, test et [ sont des modules intégrés au shell.

Le site double support qui est un mot-clé de l'interpréteur de commandes, permet de bénéficier de fonctionnalités supplémentaires. Par exemple, vous pouvez utiliser && et || au lieu de -a et -o et il y a un opérateur de correspondance d'expression régulière =~ .

De plus, dans un test simple, les crochets doubles semblent être évalués beaucoup plus rapidement que les crochets simples.

$ time for ((i=0; i<10000000; i++)); do [[ "$i" = 1000 ]]; done

real    0m24.548s
user    0m24.337s
sys 0m0.036s
$ time for ((i=0; i<10000000; i++)); do [ "$i" = 1000 ]; done

real    0m33.478s
user    0m33.478s
sys 0m0.000s

Les accolades, en plus de délimiter un nom de variable sont utilisées pour expansion des paramètres pour que vous puissiez faire des choses comme :

  • Tronquer le contenu d'une variable

    $ var="abcde"; echo ${var%d*}
    abc
  • Faites des substitutions similaires à sed

    $ var="abcde"; echo ${var/de/12}
    abc12
  • Utiliser une valeur par défaut

    $ default="hello"; unset var; echo ${var:-$default}
    hello
  • et plusieurs autres

De plus, les expansions d'accolades créent des listes de chaînes de caractères qui sont généralement itérées dans des boucles :

$ echo f{oo,ee,a}d
food feed fad

$ mv error.log{,.OLD}
(error.log is renamed to error.log.OLD because the brace expression
expands to "mv error.log error.log.OLD")

$ for num in {000..2}; do echo "$num"; done
000
001
002

$ echo {00..8..2}
00 02 04 06 08

$ echo {D..T..4}
D H L P T

Notez que les fonctions de zéro en tête et d'incrémentation n'étaient pas disponibles avant Bash 4.

Merci à gboffi de m'avoir rappelé les expansions d'accolades.

Les doubles parenthèses sont utilisées pour opérations arithmétiques :

((a++))

((meaning = 42))

for ((i=0; i<10; i++))

echo $((a + b + (14 * c)))

et ils vous permettent d'omettre le signe dollar sur les variables de type entier et tableau et d'inclure des espaces autour des opérateurs pour plus de lisibilité.

Les parenthèses simples sont également utilisées pour tableau des indices :

array[4]="hello"

element=${array[index]}

Les accolades sont nécessaires pour (la plupart/toutes ?) les références de tableaux du côté droit.

de l'éphémère m'a rappelé que les parenthèses sont également utilisées pour les sous-ensembles. Et qu'elles sont utilisées pour créer des tableaux.

array=(1 2 3)
echo ${array[1]}
2

15 votes

AVERTISSEMENT : Cette fonction est une bombe à fourche, ne l'exécutez pas. Voir : fr.wikipedia.org/wiki/Fork_bomb

5 votes

Ce n'est une bombe à fourche que si vous l'invoquez avec un élément supplémentaire : .

8 votes

Aussi pour être complet, je viens de tomber sur ceci dans un vieux script : $[expression] ; il s'agit de l'ancienne syntaxe d'expression arithmétique, dépréciée, pour la nouvelle syntaxe préférée : $((expression))

393voto

Carl Norum Points 114072
  1. Une seule parenthèse ( [ ) appelle en fait un programme nommé [ ; man test ou man [ pour plus d'informations. Exemple :

    $ VARIABLE=abcdef
    $ if [ $VARIABLE == abcdef ] ; then echo yes ; else echo no ; fi
    yes
  2. La double parenthèse ( [[ ) fait la même chose (en gros) qu'un simple crochet, mais c'est un buildin de bash.

    $ VARIABLE=abcdef
    $ if [[ $VARIABLE == 123456 ]] ; then echo yes ; else echo no ; fi
    no
  3. Parenthèses ( () ) sont utilisés pour créer un sous-shell. Par exemple :

    $ pwd
    /home/user 
    $ (cd /tmp; pwd)
    /tmp
    $ pwd
    /home/user

    Comme vous pouvez le constater, le sous-shell vous permet d'effectuer des opérations sans affecter l'environnement du shell actuel.

  4. (a) Les accolades ( {} ) sont utilisés pour identifier sans ambiguïté les variables. Exemple :

    $ VARIABLE=abcdef
    $ echo Variable: $VARIABLE
    Variable: abcdef
    $ echo Variable: $VARIABLE123456
    Variable:
    $ echo Variable: ${VARIABLE}123456
    Variable: abcdef123456

    (b) Les accolades sont également utilisées pour exécuter une séquence de commandes dans le programme actuel contexte de l'obus, par exemple

    $ { date; top -b -n1 | head ; } >logfile 
    # 'date' and 'top' output are concatenated, 
    # could be useful sometimes to hunt for a top loader )
    
    $ { date; make 2>&1; date; } | tee logfile
    # now we can calculate the duration of a build from the logfile

Il y a une différence syntaxique subtile avec ( ) Cependant, (voir référence bash ) ; essentiellement, un point-virgule ; après la dernière commande entre accolades est indispensable, et les accolades { , } doit être entouré d'espaces.

29 votes

Bien, [ est en fait un buildin dans Bash, mais il est censé agir comme /bin/[ par opposition à la [[ builtin. [[ a des caractéristiques différentes, comme des opérations plus logiques et des rôles de cotation différents. En outre, les parenthèses simples sont également utilisées pour les tableaux, la substitution de processus et les goujons étendus ; les parenthèses doubles sont utilisées pour l'arithmétique ; les accolades {} sont utilisés pour le regroupement de commandes ou pour une multitude de types d'expansion de paramètres, d'accolades ou de séquences. Je suis sûr d'avoir oublié d'autres utilisations...

6 votes

Les double-effets dans l'expression if [ $VARIABLE == abcdef ] est un bashisme qui -- bien qu'il fonctionne -- devrait probablement être évité ; soit utiliser explicitement bash ( if [[ ...==...]] ) ou indiquer clairement que vous utilisez le conditionnel plus traditionnel ( if [ "$VARIABLE" = "abcdef" ] ). On peut dire que les scripts devraient commencer par être aussi simples et portables que possible, jusqu'à ce qu'ils aient vraiment besoin de fonctionnalités spécifiques à bash (pour une raison ou une autre). Mais dans tous les cas, l'intention doit être claire ; "=" et "==" et "[[" et "[" fonctionnent différemment et leur utilisation doit être cohérente.

3 votes

@michael_n : +1 pour cette remarque. En passant, j'adore les scripts, mais je trouve assez gênant que la méthode portable consiste à tester par l'intermédiaire de [ "$var" = ".."] au lieu de == alors qu'en C, il s'agirait d'une affectation au lieu d'un test (ce qui est une cause fréquente de bogues)... pourquoi n'a-t-on pas... test utiliser == au lieu de = ? quelqu'un le sait ?

344voto

Yola Points 2650

Supports

if [ CONDITION ]    Test construct  
if [[ CONDITION ]]  Extended test construct  
Array[1]=element1   Array initialization  
[a-z]               Range of characters within a Regular Expression
$[ expression ]     A non-standard & obsolete version of $(( expression )) [1]

[1] http://wiki.bash-hackers.org/scripting/obsolete

Bretelles bouclées

${variable}                             Parameter substitution  
${!variable}                            Indirect variable reference  
{ command1; command2; . . . commandN; } Block of code  
{string1,string2,string3,...}           Brace expansion  
{a..z}                                  Extended brace expansion  
{}                                      Text replacement, after find and xargs

Parenthèses

( command1; command2 )             Command group executed within a subshell  
Array=(element1 element2 element3) Array initialization  
result=$(COMMAND)                  Command substitution, new style  
>(COMMAND)                         Process substitution  
<(COMMAND)                         Process substitution 

Parenthèses doubles

(( var = 78 ))            Integer arithmetic   
var=$(( 20 + 5 ))         Integer arithmetic, with variable assignment   
(( var++ ))               C-style variable increment   
(( var-- ))               C-style variable decrement   
(( var0 = var1<98?9:21 )) C-style ternary operation

0 votes

@Yola, pourriez-vous expliquer ce que signifie exactement $(varname) ? Dans les projets Xcode d'Apple, je peux spécifier des chemins de fichiers comme script entrée/sortie. Si je spécifie $SRC_ROOT/myFile.txt ou ${SRC_ROOT}/myFile.txt (la var SRC_ROOT est exportée par le système de construction) - cela ne fonctionne pas. Seul $(SRC_ROOT)/myFile.txt fonctionne. Quelle pourrait être la raison ? Le nom de la var n'est pas une commande ?

2 votes

@MottiShneor, dans votre cas $(varname) n'est pas lié à la syntaxe bash. Il fait partie de Syntaxe du Makefile .

0 votes

Non, Xcode ne construit pas en utilisant des makefile et ses variables sont des variables d'environnement. Les processus propriétaires du système de construction de Xcode lisent les valeurs de ces variables d'environnement prédéfinies. Les étapes de construction personnalisée sont juste des scripts shell normaux (bash ou autre) et ont accès aux mêmes variables.

24voto

kzh Points 5098

Je voulais juste ajouter ceci de TLDP :

~:$ echo $SHELL
/bin/bash

~:$ echo ${#SHELL}
9

~:$ ARRAY=(one two three)

~:$ echo ${#ARRAY}
3

~:$ echo ${TEST:-test}
test

~:$ echo $TEST

~:$ export TEST=a_string

~:$ echo ${TEST:-test}
a_string

~:$ echo ${TEST2:-$TEST}
a_string

~:$ echo $TEST2

~:$ echo ${TEST2:=$TEST}
a_string

~:$ echo $TEST2
a_string

~:$ export STRING="thisisaverylongname"

~:$ echo ${STRING:4}
isaverylongname

~:$ echo ${STRING:6:5}
avery

~:$ echo ${ARRAY[*]}
one two one three one four

~:$ echo ${ARRAY[*]#one}
two three four

~:$ echo ${ARRAY[*]#t}
one wo one hree one four

~:$ echo ${ARRAY[*]#t*}
one wo one hree one four

~:$ echo ${ARRAY[*]##t*}
one one one four

~:$ echo $STRING
thisisaverylongname

~:$ echo ${STRING%name}
thisisaverylong

~:$ echo ${STRING/name/string}
thisisaverylongstring

20 votes

Remarquez que echo ${#ARRAY} en affiche trois, en raison du premier élément de l'élément ARRAY contient trois caractères, et non parce qu'il contient trois éléments ! Pour imprimer le nombre d'éléments, utilisez echo ${#ARRAY[@]} .

0 votes

@zeal ${TEST:-test} est égal à $TEST si la variable TEST existe, sinon il renvoie simplement la chaîne "test". Il existe une autre version qui fait encore plus : ${TEST:=test} --- qui est également égal à $TEST si TEST existe, mais s'il n'existe pas, il crée la variable TEST et attribue une valeur "test" et devient également la valeur de l'expression entière.

19voto

pabouk Points 277

Parenthèses dans la définition de la fonction

Parenthèses () sont utilisés dans la définition des fonctions :

function_name () { command1 ; command2 ; }

C'est la raison pour laquelle vous devez échapper aux parenthèses même dans les paramètres de commande :

$ echo (
bash: syntax error near unexpected token `newline'

$ echo \(
(

$ echo () { command echo The command echo was redefined. ; }
$ echo anything
The command echo was redefined.

0 votes

Oh, j'ai essayé sur le csh. C'est ma faute. Quand j'essaie sur bash, ça marche. Je ne connaissais pas la commande 'command' de bash.

0 votes

Comment puis-je annuler la redéfinition de la commande echo() ? (sans rouvrir le bash)

2 votes

@ChanKim : unset -f echo . Voir help unset .

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X