web-dev-qa-db-fra.com

Comment utiliser des crochets simples ou doubles, des parenthèses, des accolades

Je suis dérouté par l’utilisation des crochets, des parenthèses, des accolades dans Bash, ainsi que par la différence entre leurs formes simple et double. Y a-t-il une explication claire?

625
Tim

Dans Bash, test et [ sont des commandes intégrées au shell.

Le double crochet , qui est un mot clé Shell, active des fonctionnalités supplémentaires. Par exemple, vous pouvez utiliser && et || au lieu de -a et -o et il existe un opérateur de correspondance d'expression régulière =~.

De plus, dans un test simple, les doubles crochets semblent s’évaluer beaucoup plus rapidement que les 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 de paramètre afin que vous puissiez faire des choses comme:

  • Tronquer le contenu d'une variable

    $ var="abcde"; echo ${var%d*}
    abc
    
  • Faire 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

En outre, les extensions d'accolade créent des listes de chaînes 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 et d’incrément n’étaient pas disponibles avant Bash 4.

Merci à gboffi de m'avoir rappelé l’expansion des corsets.

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 les signes dollar des variables entières et matricielles et d’inclure des espaces autour des opérateurs pour plus de lisibilité.

Des crochets simples sont également utilisés pour tablea indices:

array[4]="hello"

element=${array[index]}

Les accolades sont nécessaires pour (la plupart/toutes?) Les références de tableau sur le côté droit.

Le commentaire de ephemient m'a rappelé que les parenthèses sont également utilisées pour les sous-shell. Et qu'ils sont utilisés pour créer des tableaux.

array=(1 2 3)
echo ${array[1]}
2
570
Dennis Williamson
  1. Un seul crochet ([) appelle généralement 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. Le double crochet ([[) fait la même chose (en gros) qu’un seul crochet, mais est un élément intégré bash.

    $ VARIABLE=abcdef
    $ if [[ $VARIABLE == 123456 ]] ; then echo yes ; else echo no ; fi
    no
    
  3. Les parenthèses (()) sont utilisées 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 a permis d'effectuer des opérations sans affecter l'environnement du shell actuel.

  4. (a) Les accolades ({}) permettent d'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 contexte actuel Shell, 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 {, } doivent être entouré d'espaces.

320
Carl Norum

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

Accolades

${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 

Double parenthèse

(( 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
282
Yola

Je voulais juste les ajouter 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
23
kzh

Parenthèses dans la définition de fonction

Les parenthèses () sont utilisées dans la définition de fonction:

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.
18
pabouk

La différence entre test , [ et [[ est expliqué en détail dans le BashFAQ .

En résumé, test implémente l'ancienne syntaxe portable de la commande. Dans presque tous les coquillages (les plus vieux coquillages Bourne sont l'exception), [est synonyme de test (mais nécessite un argument final de]). Bien que tous les shells modernes aient des implémentations intégrées de [ il existe toujours un exécutable externe de ce nom, par exemple. /poubelle/[.

[[est une nouvelle version améliorée de celui-ci, qui est un mot clé, pas un programme. Ceci a des effets bénéfiques sur la facilité d'utilisation, comme indiqué ci-dessous. [[est compris par KornShell et BASH (par exemple, 2.03), mais pas par les anciens POSIX et BourneShell.

Et la conclusion:

Quand faut-il utiliser la nouvelle commande de test [[ et quand l'ancienne [? Si la portabilité vers BourneShell est un problème, l'ancienne syntaxe doit être utilisée. Si par contre le script nécessite BASH ou KornShell, la nouvelle syntaxe est beaucoup plus souple.

18
fwhacking
Truncate the contents of a variable

$ var="abcde"; echo ${var%d*}
abc

Make substitutions similar to sed

$ var="abcde"; echo ${var/de/12}
abc12

Use a default value

$ default="hello"; unset var; echo ${var:-$default}
hello
0
vuppala srikar