je peux écrire
VAR=$VAR1
VAR=${VAR1}
VAR="$VAR1"
VAR="${VAR1}"
le résultat final me semble à peu près le même. Pourquoi devrais-je écrire l'un ou l'autre? y en a-t-il qui ne sont pas portables / POSIX?
je peux écrire
VAR=$VAR1
VAR=${VAR1}
VAR="$VAR1"
VAR="${VAR1}"
le résultat final me semble à peu près le même. Pourquoi devrais-je écrire l'un ou l'autre? y en a-t-il qui ne sont pas portables / POSIX?
Réponses:
VAR=$VAR1
est une version simplifiée de VAR=${VAR1}
. La seconde peut faire certaines choses que la première ne peut pas faire, par exemple référencer un index de tableau (non portable) ou supprimer une sous-chaîne (POSIX-portable). Voir la section Plus d'informations sur les variables du Guide Bash pour les débutants et le développement de paramètres dans les spécifications POSIX.
L'utilisation de guillemets autour d'une variable telle que rm -- "$VAR1"
ou rm -- "${VAR}"
est une bonne idée. Cela fait du contenu de la variable une unité atomique. Si la valeur de la variable contient des blancs (ainsi, des caractères dans la $IFS
variable spéciale, des blancs par défaut) ou des caractères globaux et que vous ne le citez pas, alors chaque mot est pris en compte pour la génération du nom de fichier (globbing) dont l'expansion multiplie autant d'arguments que vous le souhaitez. faites-vous.
$ find .
.
./*r*
./-rf
./another
./filename
./spaced filename
./another spaced filename
./another spaced filename/x
$ var='spaced filename'
# usually, 'spaced filename' would come from the output of some command and you weren't expecting it
$ rm $var
rm: cannot remove 'spaced': No such file or directory
# oops! I just ran 'rm spaced filename'
$ var='*r*'
$ rm $var
# expands to: 'rm' '-rf' '*r*' 'another spaced filename'
$ find .
.
./another
./spaced filename
./another spaced filename
$ var='another spaced filename'
$ rm -- "$var"
$ find .
.
./another
./spaced filename
Sur la portabilité: Selon POSIX.1-2008 section 2.6.2 , les accolades sont facultatives.
var1=$var
expansion donne une erreur?
export VAR=$VAR1
. Quant aux accolades, elles sont facultatives (consultez le quatrième paragraphe de la section que vous avez citée; c'est le cas de tous les shells antérieurs à POSIX et POSIX).
${VAR}
et $VAR
sont exactement équivalents. Pour un développement de variable simple, la seule raison à utiliser ${VAR}
est le moment où l'analyse capturerait trop de caractères dans le nom de la variable, comme dans ${VAR1}_$VAR2
(qui, sans accolades, équivaudrait à ${VAR1_}$VAR2
). La plupart des extensions (parées ${VAR:=default}
, ${VAR#prefix}
...) nécessitent des accolades.
Dans une affectation de variable, le fractionnement du champ ( par exemple le fractionnement à des espaces de la valeur) et l' expansion du chemin (c. -à- englobement) sont désactivés, donc VAR=$VAR1
est exactement équivalente à VAR="$VAR1"
, dans toutes les coquilles POSIX et dans tous les poissons pré-Posix que je l' ai entendu parler de . (Réf. POSIX: commandes simples ). Pour la même raison, VAR=*
définit de manière fiable VAR
la chaîne littérale *
; bien sûr VAR=a b
met VAR
à a
puisque le b
est un mot séparé en premier lieu. En règle générale, les guillemets doubles ne sont pas nécessaires lorsque la syntaxe du shell attend un seul mot, par exemple, danscase … in
(mais pas dans le modèle), mais même là, vous devez faire attention: par exemple, POSIX spécifie queLes cibles de redirection ( >$filename
) ne nécessitent pas de guillemets dans les scripts, mais quelques shells, y compris bash, requièrent les guillemets doubles, même dans les scripts. Voir Quand la double cotation est-elle nécessaire? pour une analyse plus approfondie.
Vous avez besoin des guillemets dans d'autres cas, en particulier dans export VAR="${VAR1}"
(ce qui peut être écrit de manière équivalente export "VAR=${VAR1}"
) dans de nombreux shells (POSIX laisse ce cas ouvert). La similitude de ce cas avec des affectations simples et la nature dispersée de la liste des cas dans lesquels vous n’avez pas besoin de guillemets, sont la raison pour laquelle je recommande d’utiliser des guillemets doubles à moins que vous ne souhaitiez scinder et glob.
IFS
caractère, car je veux en prendre l'habitude. La seule exception est que je ne cite pas la valeur lors d'une affectation de variable (sauf si requis, comme lorsque la valeur contient un espace). Cela rend la mise en évidence de la syntaxe de l'éditeur plus utile lorsqu'il existe des substitutions de commandes telles que FOO=$(BAR=$(BAZ=blah; printf %s "${BAZ}"); printf %s "${BAR}")
. Plutôt que de tout colorer la couleur "chaîne", j'obtiens la coloration syntaxique du code imbriqué. C'est aussi pourquoi j'évite les backticks.
>$file
est OK dans les scripts POSIX, il n'est pas dans bash même s'il n'est pas interactif (sauf si la conformité POSIX est appliquée avec $POSIXLY_CORRECT
ou --posix
...).
VAR=$VAR1
, j'ai parfois été surpris par le fait local VAR=$VAR1
que je me souviens d'avoir travaillé différemment à certains égards, au moins dans certains obus. Mais atm, je ne peux pas reproduire la divergence.
local VAR=$VAR1
est comme export VAR=$VAR1
, cela dépend de la coquille.
Considérez que les guillemets doubles sont utilisés pour les extensions variables et les guillemets simples pour les guillemets forts, c'est-à-dire sans expansion.
this='foo'
that='bar'
these="$this"
those='$that'
for item in "$this" "$that" "$these" "$those"; do echo "$item"; done
foo
bar
foo
$that
Il peut être intéressant de mentionner que vous devez utiliser la citation chaque fois que possible pour plusieurs raisons, dont la meilleure est qu’elle est considérée comme une pratique exemplaire et par souci de lisibilité. Aussi, parce que Bash est parfois bizarre et souvent pour des manières apparemment illogiques ou déraisonnables / inattendues, et que la citation modifie les attentes implicites en explicites, ce qui réduit cette surface d'erreur (ou son potentiel).
Et bien qu'il soit tout à fait légal de ne pas citer, et que cela fonctionne dans la plupart des cas, cette fonctionnalité est fournie pour plus de commodité et est probablement moins portable. la pratique entièrement formelle qui garantit de refléter l'intention et les attentes consiste à citer.
Considérons maintenant que la construction "${somevar}"
est utilisée pour les opérations de substitution. Plusieurs cas d'utilisation, tels que le remplacement et les tableaux.
thisfile='foobar.txt.bak'
foo="${thisfile%.*}" # removes shortest part of value in $thisfile matching after '%' from righthand side
bar="${thisfile%%.*}" # removes longest matching
for item in "$foo" "$bar"; do echo "$item"; done
foobar.txt
foobar
foobar='Simplest, least effective, least powerful'
# ${var/find/replace_with}
foo="${foobar/least/most}" #single occurrence
bar="${foobar//least/most}" #global occurrence (all)
for item in "$foobar" "$foo" "$bar"; do echo "$item"; done
Simplest, least effective, least powerful
Simplest, most effective, least powerful
Simplest, most effective, most powerful
mkdir temp
# create files foo.txt, bar.txt, foobar.txt in temp folder
touch temp/{foo,bar,foobar}.txt
# alpha is array of output from ls
alpha=($(ls temp/*))
echo "$alpha" # temp/foo.txt
echo "${alpha}" # temp/foo.txt
echo "${alpha[@]}" # temp/bar.txt temp/foobar.txt temp/foo.txt
echo "${#alpha}" # 12 # length of first element (implicit index [0])
echo "${#alpha[@]}" # 3 # number of elements
echo "${alpha[1]}" # temp/foobar.txt # second element
echo "${#alpha[1])" # 15 # length of second element
for item in "${alpha[@]}"; do echo "$item"; done
temp/bar.txt
temp/foobar.txt
temp/foo.txt
Tout cela ne fait qu’effleurer la surface de la "${var}"
construction de substitution. La référence définitive pour les scripts shell Bash est la référence en ligne libre, TLDP The Linux Documentation Projecthttps://www.tldp.org/LDP/abs/html/parameter-substitution.html
ls -la
lrwxrwxrwx. 1 root root 31 Nov 17 13:13 prodhostname
lrwxrwxrwx. 1 root root 33 Nov 17 13:13 testhostname
lrwxrwxrwx. 1 root root 32 Nov 17 13:13 justname
fin ensuite:
env=$1
if [ ! -f /dirname/${env}hostname ]
mérite d'être cité comme exemple plus clair d'utilisation de curlies