Réponses:
Dans Bash, test
et [
sont intégrés dans le shell.
Le double crochet , qui est un mot-clé shell, permet des 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'expressions régulières =~
.
De plus, dans un test simple, les doubles crochets semblent é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 l' expansion des paramètres 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
Utilisez une valeur par défaut
$ default="hello"; unset var; echo ${var:-$default}
hello
et plusieurs autres
De plus, les extensions d'accolade créent des listes de chaînes qui sont généralement répétées en 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 principales fonctionnalités de zéro et d'incrémentation n'étaient pas disponibles avant Bash 4.
Merci à gboffi de m'avoir rappelé les extensions de bretelles.
Les parenthèses doubles sont utilisées pour les 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 sur les variables d'entier et de tableau et d'inclure des espaces autour des opérateurs pour plus de lisibilité.
Des parenthèses simples sont également utilisées pour les indices de tableau :
array[4]="hello"
element=${array[index]}
Des accolades sont requises pour (la plupart / toutes?) Les références de tableau sur le côté droit.
Le commentaire de l'éphémient m'a rappelé que les parenthèses sont également utilisées pour les sous-coquilles. Et qu'ils sont utilisés pour créer des tableaux.
array=(1 2 3)
echo ${array[1]}
2
:
.
$[expression]
:; il s'agit de l'ancienne syntaxe d'expression arithmétique obsolète pour la nouvelle syntaxe préférée:$((expression))
bash
création de séquences, comme mentionné en périphérie ci-dessous ( stackoverflow.com/a/8552128/2749397 ) Comme je voudrais commenter un peu cette fonctionnalité (comme vous ne l'avez pas mentionnée ;-) Je ' m prendre la liberté d'utiliser la réponse la plus votée comme véhicule ... Deux exemples de littéraux de séquence: echo {01..12}
-> 01 02 03 04 05 06 07 08 09 10 11 12
(notez le zéro initial); echo {C..Q}
-> C D E F G H I J K L M N O P Q
. Son utilisation principale est dans les boucles, par exemple, for cnt in {01..12} ; do ... ${cnt} ... ; done
echo {01..12..2}
-> "01 03 05 07 09 11". Merci pour le rappel des séquences. Je vais l'ajouter à ma réponse.
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
Le double crochet ( [[
) fait la même chose (fondamentalement) qu'un simple crochet, mais est un bash intégré.
$ VARIABLE=abcdef
$ if [[ $VARIABLE == 123456 ]] ; then echo yes ; else echo no ; fi
no
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 voir, le sous-shell vous a permis d'effectuer des opérations sans affecter l'environnement du shell actuel.
(a) Les accolades ( {}
) sont utilisées 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 contexte actuel du 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 existe cependant une subtile différence syntaxique avec ( )
(voir la référence bash ); essentiellement, un point - virgule ;
après la dernière commande entre accolades est une nécessité, et les accolades {
, }
doit être entouré par des espaces.
[
c'est en fait une fonction intégrée dans Bash, mais elle est censée agir comme /bin/[
par opposition à la fonction [[
intégrée. [[
a des fonctionnalités différentes, comme des opérations plus logiques et différents rôles de citation. De plus: des parenthèses simples sont également utilisées pour les tableaux, la substitution de processus et les globs étendus; des parenthèses doubles sont utilisées pour l'arithmétique; les accolades {}
sont utilisées pour le regroupement de commandes ou une multitude de types d'expansion de paramètres ou d'extension d'accolade ou d'extension de séquence. Je suis sûr que j'ai manqué d'autres utilisations aussi ...
if [ $VARIABLE == abcdef ]
est un bashisme qui - bien que cela fonctionne - devrait probablement être évité; utilisez explicitement bash ( if [[ ...==...]]
) ou indiquez clairement que vous utilisez le conditionnel ( if [ "$VARIABLE" = "abcdef" ]
) plus traditionnel . On peut dire que les scripts devraient commencer 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.
[ "$var" = ".."]
au lieu de ==
, alors qu'en C il attribuerait au lieu de tester (et est une cause assez courante de bugs) ... pourquoi didn pas test
utiliser à la ==
place de =
? quelqu'un sait?
/usr/bin/[
n'est pas un lien symbolique vers le /usr/bin/test
, et plus encore: ces programmes ont même quelques tailles différentes!
)
fait partie de la case
syntaxe de l' instruction pour terminer une ligne de casse. Il n'a pas de parenthèse ouvrante. Cela m'a jeté la première fois que je l'ai vu.
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
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
$(varname)
n'est pas lié à la syntaxe bash. Cela fait partie de la syntaxe Makefile .
$(varname)
n'a aucun rapport avec la syntaxe bash dans votre cas.
Je voulais juste ajouter ceux-ci à partir 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
echo ${#ARRAY}
affiche trois, à cause du premier élément du ARRAY
contient trois caractères, pas parce qu'il contient trois éléments! Pour imprimer le nombre d'éléments, utilisez echo ${#ARRAY[@]}
.
${TEST:-test}
est égal à $TEST
si la variable TEST
existe, sinon elle renvoie simplement la chaîne "test". Il existe une autre version qui fait encore plus: ${TEST:=test}
--- qui équivaut également à $TEST
si TEST existe, mais chaque fois que cela n'existe pas, il crée la variable TEST
et attribue une valeur "test" et devient également la valeur de l'expression entière.
La différence entre test , [ et [[ est expliquée en détail dans le BashFAQ .
Pour faire court: test implémente l'ancienne syntaxe portable de la commande. Dans presque tous les shells (les plus anciens shells 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 généralement toujours un exécutable externe de ce nom, par exemple / bin / [.
[[est une nouvelle version améliorée de celui-ci, qui est un mot-clé, pas un programme. Cela 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 ou BourneShell.
Et la conclusion:
Quand faut-il utiliser la nouvelle commande de test [[et quand l'ancienne [? Si la portabilité vers le 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 flexible.
Les parenthèses ()
sont utilisées dans la définition des fonctions:
function_name () { command1 ; command2 ; }
C'est la raison pour laquelle vous devez échapper les 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.
unset -f echo
. Tu vois help unset
.
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