Si vous suivez unix.stackexchange.com depuis un moment, vous devriez savoir maintenant que laisser une variable non citée dans le contexte de liste (comme dans echo $var
) dans les shells Bourne / POSIX (zsh étant l'exception) a une signification toute particulière et ne devrait pas être fait à moins d’avoir une très bonne raison de le faire.
Il est discuté longuement dans un certain nombre de questions-réponses ici (Exemples: ? Pourquoi mon starter script shell sur les espaces ou autres caractères spéciaux , Quand des guillemets doubles nécessaire? , Extension d'une variable shell et l' effet de glob et divisé sur elle , Quoted vs extension de chaîne sans guillemets)
C’est le cas depuis la publication initiale du shell Bourne à la fin des années 70 et le shell Korn n’a pas été modifié par celui-ci (l’un des plus grands regrets de David Korn (question n ° 7) ) ou bash
qui a essentiellement copié le shell Korn, comment cela a été spécifié par POSIX / Unix.
Maintenant, nous voyons encore un certain nombre de réponses ici et même parfois de code shell publié publiquement où les variables ne sont pas citées. Vous auriez pensé que les gens auraient appris maintenant.
D'après mon expérience, il y a principalement 3 types de personnes qui omettent de citer leurs variables:
débutants. Celles-ci peuvent être excusées car il s'agit d'une syntaxe totalement non intuitive. Et c'est notre rôle sur ce site de les éduquer.
les gens oublieux.
des gens qui ne sont pas convaincus, même après des coups répétés, qui pensent que l'auteur du shell Bourne ne voulait sûrement pas citer toutes nos variables .
Peut-être pouvons-nous les convaincre si nous exposons le risque associé à ce type de comportement.
Quelle est la pire chose qui puisse éventuellement arriver si vous oubliez de citer vos variables. Est-ce vraiment si mauvais?
De quel type de vulnérabilité parle-t-on ici?
Dans quels contextes cela peut-il poser problème?
Réponses:
Préambule
Premièrement, je dirais que ce n'est pas la bonne façon de résoudre le problème. C'est un peu comme dire " tu ne devrais pas assassiner des gens, sinon tu iras en prison ".
De même, vous ne citez pas votre variable car sinon, vous introduisez des vulnérabilités de sécurité. Vous citez vos variables car il est faux de ne pas le faire (mais si la peur de la prison peut aider, pourquoi pas).
Un petit résumé pour ceux qui viennent de sauter dans le train.
Dans la plupart des shells, laisser un développement variable sans guillemets (bien que cela (et le reste de cette réponse) s'applique également à la substitution de commande (
`...`
ou$(...)
) et au développement arithmétique ($((...))
ou$[...]
)) a une signification toute particulière. La meilleure façon de le décrire est que cela revient à invoquer une sorte d’ opérateur implicite scindé + glob¹ .dans une autre langue serait écrit quelque chose comme:
$var
est d'abord divisé en une liste de mots selon des règles complexes impliquant le$IFS
paramètre spécial (la partie divisée ), puis chaque mot résultant de cette division est considéré comme un motif qui est développé en une liste de fichiers qui lui correspond (la partie globale ) .Par exemple, si
$var
contient*.txt,/var/*.xml
et$IFS
contient,
,cmd
serait appelé avec un certain nombre d'arguments, le premiercmd
et les suivants étant lestxt
fichiers du répertoire en cours et lesxml
fichiers du répertoire/var
.Si vous vouliez appeler
cmd
avec seulement deux arguments littérauxcmd
et*.txt,/var/*.xml
écrire, vous écririez:qui serait dans votre autre langue plus familière:
Qu'entendons-nous par vulnérabilité dans un shell ?
Après tout, on sait depuis la nuit des temps que les scripts shell ne doivent pas être utilisés dans des contextes sensibles à la sécurité. OK, laisser une variable sans guillemets est un bogue, mais cela ne fait pas beaucoup de mal, n'est-ce pas?
Bien que quiconque vous dise que les scripts shell ne doivent jamais être utilisés pour les CGI Web, ou que, heureusement, la plupart des systèmes n’autorisent plus les scripts shell setuid / setgid de nos jours, le shellshock (le bogue bash exploitable à distance titre en septembre 2014) a révélé que les shells sont encore largement utilisés là où ils ne devraient probablement pas: dans les CGI, dans les scripts de hook client DHCP, dans les commandes sudoers, invoqués par (sinon comme ) les commandes setuid ...
Parfois sans le savoir. Par exemple,
system('cmd $PATH_INFO')
dans un scriptphp
/perl
/python
CGI, un shell est interprété pour interpréter cette ligne de commande (sans parler du fait qu’ilcmd
peut s’agir d’un script shell et que son auteur ne s’est jamais attendu à ce qu’il soit appelé depuis un CGI).Vous avez une vulnérabilité quand il y a un chemin pour l'ascension des privilèges, c'est-à-dire quand quelqu'un (appelons-le l'attaquant ) est capable de faire quelque chose qu'il n'est pas censé faire.
Invariablement, cela signifie que l'attaquant fournit des données, ces données étant traitées par un utilisateur / processus privilégié qui fait par inadvertance quelque chose qu'il ne devrait pas faire, dans la plupart des cas à cause d'un bogue.
En gros, vous rencontrez un problème lorsque votre code de bogue traite des données sous le contrôle de l'attaquant .
À présent, la provenance de ces données n’est pas toujours évidente , et il est souvent difficile de dire si votre code parviendra à traiter des données non fiables.
En ce qui concerne les variables, dans le cas d'un script CGI, il est assez évident que les données sont les paramètres CGI GET / POST et des éléments tels que les cookies, le chemin d'accès, les paramètres de l'hôte ....
Pour un script setuid (exécuté en tant qu'utilisateur lorsqu'il est appelé par un autre), il s'agit des arguments ou des variables d'environnement.
Les noms de fichiers sont un autre vecteur très courant. Si vous obtenez une liste de fichiers à partir d’un répertoire, il est possible que l’attaquant y ait planté des fichiers .
À cet égard, même à l'invite d'un shell interactif, vous pourriez être vulnérable (lors du traitement de fichiers dans
/tmp
ou~/tmp
par exemple).Même un
~/.bashrc
peut être vulnérable (par exemple,bash
l'interprète lorsqu'il est appeléssh
pour exécuter un processusForcedCommand
similaire à celui d'git
un déploiement de serveur avec certaines variables sous le contrôle du client).Désormais, un script ne peut pas être appelé directement pour traiter des données non fiables, mais il peut être appelé par une autre commande. Ou votre code incorrect peut être copié-collé dans des scripts (par vous 3 ans en arrière ou l'un de vos collègues). Les réponses dans les sites de questions-réponses sont particulièrement critiques , car vous ne saurez jamais où les copies de votre code pourraient se retrouver.
Aux affaires; c'est comment?
Laisser une variable (ou une substitution de commande) sans guillemets est de loin la source de vulnérabilités en matière de sécurité associée au code shell. En partie parce que ces bogues se traduisent souvent par des vulnérabilités, mais aussi parce qu'il est si courant de voir des variables non citées.
En fait, lorsque vous recherchez des vulnérabilités dans le code shell, la première chose à faire est de rechercher des variables non citées. Il est facile de repérer, souvent un bon candidat, généralement facile de retrouver des données contrôlées par des attaquants.
Il existe un nombre infini de façons dont une variable non citée peut se transformer en vulnérabilité. Je vais juste donner quelques tendances communes ici.
Divulgation d'information
La plupart des gens se heurteront à des bogues associés à des variables sans guillemets à cause de la partie scindée (par exemple, il est courant que les fichiers comportent des espaces dans leurs noms et que la valeur par défaut est IFS). Beaucoup de gens vont négliger la partie glob . La partie glob est au moins aussi dangereuse que la partie scindée .
Globbing sur une entrée externe non authentifiée signifie que l'attaquant peut vous faire lire le contenu de n'importe quel répertoire.
Dans:
si
$unsanitised_external_input
contient/*
, cela signifie que l'attaquant peut voir le contenu de/
. Pas grand chose. Cela devient cependant plus intéressant, avec la/home/*
liste des noms d’utilisateur de la machine/tmp/*
,/home/*/.forward
des astuces sur d’autres pratiques dangereuses,/etc/rc*/*
des services activés ... Inutile de les nommer individuellement. Une valeur de/* /*/* /*/*/*...
va simplement lister tout le système de fichiers.Vulnérabilités de déni de service.
Prenant le cas précédent un peu trop loin et nous avons un DoS.
En fait, toute variable non citée dans le contexte de liste avec une entrée non authentifiée est au moins une vulnérabilité de type DoS.
Même les scripteurs experts oublient souvent de citer des choses telles que:
:
est la commande no-op. Qu'est ce qui pourrait aller mal?Cela est destiné à affecter
$1
à$QUERYSTRING
si$QUERYSTRING
était non défini. C'est un moyen rapide de rendre un script CGI appelable à partir de la ligne de commande.Cela
$QUERYSTRING
reste cependant étendu et comme il n’est pas cité, l’ opérateur split + glob est appelé.Maintenant, il y a des globs qui sont particulièrement coûteux à développer. Celui-
/*/*/*/*
ci est déjà assez mauvais car cela signifie qu’il faut lister les répertoires jusqu’à 4 niveaux. En plus de l'activité du disque et du processeur, cela signifie stocker des dizaines de milliers de chemins de fichiers (40k ici sur une VM serveur minimale, dont 10k répertoires).Désormais, cela
/*/*/*/*/../../../../*/*/*/*
signifie 40k x 10k et/*/*/*/*/../../../../*/*/*/*/../../../../*/*/*/*
est suffisant pour amener même la machine la plus puissante à ses genoux.Essayez-le vous-même (préparez-vous à ce que votre machine tombe en panne ou se bloque):
Bien sûr, si le code est:
Ensuite, vous pouvez remplir le disque.
Il suffit de faire une recherche google sur shell cgi ou bash cgi ou ksh cgi et vous trouverez quelques pages qui vous montreront comment écrire des CGI dans des shells. Notez que la moitié de ceux qui traitent les paramètres sont vulnérables.
Même celui de David Korn est vulnérable (regardez la gestion des cookies).
jusqu'à vulnérabilités d'exécution de code arbitraire
L'exécution de code arbitraire est le pire type de vulnérabilité, car si l'attaquant peut exécuter n'importe quelle commande, il n'y a aucune limite à ce qu'il peut faire.
C'est généralement la partie divisée qui mène à ceux-ci. Cette division entraîne la transmission de plusieurs arguments aux commandes lorsqu'un seul est attendu. Tandis que le premier de ceux-ci sera utilisé dans le contexte attendu, les autres seront dans un contexte différent, donc potentiellement interprété différemment. Mieux avec un exemple:
Ici, l’intention était d’affecter le contenu de la
$external_input
variable shell à lafoo
awk
variable.Maintenant:
Le second mot résultant du fractionnement de
$external_input
n'est pas affecté à,foo
mais considéré comme unawk
code (ici, il exécute une commande arbitraire:)uname
.Cela est particulièrement un problème pour les commandes qui peuvent exécuter d' autres commandes (
awk
,env
,sed
(GNU un),perl
,find
...) en particulier avec les variantes GNU (qui acceptent les options après arguments). Parfois, vous ne soupçonneriez pas que des commandes soient capables d'exécuter des tâches telles queksh
,bash
ouzsh
est[
ouprintf
...Si nous créons un répertoire appelé
x -o yes
, alors le test devient positif, car nous évaluons une expression conditionnelle complètement différente.Pire, si nous créons un fichier appelé
x -a a[0$(uname>&2)] -gt 1
, avec au moins toutes les implémentations de ksh (qui inclut lessh
Unices les plus commerciaux et certains BSD), s’exécuteuname
parce que ces shells effectuent une évaluation arithmétique sur les opérateurs de comparaison numériques de la[
commande.Même chose
bash
pour un nom de fichier commex -a -v a[0$(uname>&2)]
.Bien sûr, s’ils ne peuvent pas exécuter une exécution arbitraire, l’attaquant peut s’attendre à des dommages moindres (ce qui peut aider à une exécution arbitraire). Toute commande pouvant écrire des fichiers ou modifier les autorisations, la propriété ou avoir un effet principal ou secondaire pourrait être exploitée.
Toutes sortes de choses peuvent être faites avec les noms de fichiers.
Et vous
..
finissez par rendre l’ écriture (récursive avec GNUchmod
).Les scripts effectuant un traitement automatique des fichiers dans des zones accessibles en écriture publique
/tmp
doivent être écrits avec beaucoup de soin.Qu'en est-il de
[ $# -gt 1 ]
C'est quelque chose que je trouve exaspérant. Certaines personnes ont la peine de se demander si une expansion donnée peut être problématique pour décider si elles peuvent ou non omettre les guillemets.
C'est comme dire. Hé, il semble que
$#
ne peut pas être soumis à l'opérateur split + glob, demandons au shell de le scinder + glob . Ou alors , écrivons un code incorrect simplement parce qu'il est peu probable que le bogue soit touché .Maintenant, à quel point est-ce improbable? OK,
$#
(ou$!
,$?
ou toute substitution arithmétique) ne peut contenir que des chiffres (ou-
pour certains), de sorte que la partie glob est sortie. Pour que la partie divisée fasse quelque chose, tout ce dont nous avons besoin est$IFS
de contenir des chiffres (ou-
).Avec certains coquillages,
$IFS
peut être hérité de l'environnement, mais si l'environnement n'est pas sûr, la partie est terminée de toute façon.Maintenant, si vous écrivez une fonction comme:
Cela signifie que le comportement de votre fonction dépend du contexte dans lequel elle est appelée. Ou en d'autres termes,
$IFS
devient l'un des intrants. Strictement parlant, lorsque vous écrivez la documentation de l'API pour votre fonction, cela devrait ressembler à ceci:Et le code appelant votre fonction doit s’assurer que
$IFS
ne contient pas de chiffres. Tout cela parce que vous n'aviez pas envie de taper ces 2 caractères à double guillemet.Maintenant, pour que ce
[ $# -eq 2 ]
bogue devienne une vulnérabilité, il vous faudrait en quelque sorte que la valeur de$IFS
devienne sous le contrôle de l'attaquant . En théorie, cela ne se produirait normalement que si l'attaquant réussissait à exploiter un autre bogue.Ce n'est pas du jamais vu. Il arrive souvent que des personnes oublient de nettoyer leurs données avant de les utiliser dans une expression arithmétique. Nous avons déjà vu plus haut que cela peut permettre l'exécution de code arbitraire dans certains shells, mais permet à l'attaquant de donner à toute variable une valeur entière.
Par exemple:
Et avec une
$1
valeur with(IFS=-1234567890)
, cette évaluation arithmétique a pour effet secondaire les paramètres IFS et la[
commande suivante échoue, ce qui signifie que la vérification de trop d'arguments est ignorée.Qu'en est-il lorsque l' opérateur split + glob n'est pas appelé?
Il existe un autre cas où des guillemets sont nécessaires autour des variables et autres développements: quand il est utilisé comme motif.
ne testez pas si
$a
et$b
sont les mêmes (sauf aveczsh
) mais si$a
correspond au modèle dans$b
. Et vous devez citer$b
si vous voulez comparer en tant que chaînes (la même chose dans"${a#$b}"
ou"${a%$b}"
ou"${a##*$b*}"
où$b
devrait être citée si elle ne doit pas être considérée comme un motif).Cela signifie que
[[ $a = $b ]]
peut retourner vrai dans les cas où$a
est différent de$b
(par exemple quand$a
estanything
et$b
est*
) ou peut retourner faux quand ils sont identiques (par exemple quand les deux$a
et$b
sont[a]
).Cela peut-il créer une vulnérabilité de sécurité? Oui, comme n'importe quel bug. Ici, l'attaquant peut modifier le flux de code logique de votre script et / ou briser les hypothèses émises par votre script. Par exemple, avec un code comme:
L'attaquant peut contourner le contrôle en passant
'[a]' '[a]'
.Maintenant, si ni cette correspondance de modèle ni l' opérateur split + glob ne s'appliquent, quel est le danger de laisser une variable sans guillemets?
Je dois admettre que j'écris:
Là, citer ne nuit pas, mais n'est pas strictement nécessaire.
Toutefois, l’absence de guillemets dans ces cas (par exemple, dans les réponses aux questions et réponses) a pour effet secondaire d’envoyer un message erroné aux débutants:
il peut être correct de ne pas citer de variables.Par exemple, ils peuvent commencer à penser que si
a=$b
OK est correct, alors leserait aussi (ce qui n'est pas dans beaucoup de shells , mais dans les arguments de laexport a=$b
export
commande, donc dans le contexte d'une liste) ou.env a=$b
Qu'en est- il
zsh
?zsh
n'a pas résolu la plupart de ces maladresses de conception. Enzsh
(au moins lorsqu'ils ne sont pas en mode d'émulation sh / ksh), si vous voulez diviser , ou englobement ou correspondance de motif , vous devez demander explicitement:$=var
diviser, et$~var
à glob ou pour le contenu de la variable à traiter comme un motif.Cependant, le fractionnement (mais pas la suppression) est toujours effectué implicitement lors de la substitution de commande non entre guillemets (comme dans
echo $(cmd)
).En outre, un effet secondaire parfois indésirable de ne pas citer de variable est la suppression des éléments vides . Le
zsh
comportement est similaire à ce que vous pouvez obtenir dans d’autres coques en désactivant complètement l’effacement (avecset -f
) et le dédoublement (avecIFS=''
). Toujours dedans:Il n'y aura pas de split + glob , mais si
$var
est vide, au lieu de recevoir un argument vide, ilcmd
ne recevra aucun argument.Cela peut causer des bugs (comme l'évidence
[ -n $var ]
). Cela peut éventuellement casser les attentes et les hypothèses d’un script et causer des vulnérabilités, mais je ne peux pas vous donner d’exemple pas trop farfelu pour le moment).Qu'en est- il lorsque vous avez besoin de la scission + glob opérateur?
Oui, c’est généralement le cas lorsque vous souhaitez laisser votre variable non citée. Mais ensuite, vous devez vous assurer que vous réglez correctement vos opérateurs split et glob avant de l’utiliser. Si vous ne voulez que la partie divisée et non la partie globale (ce qui est le cas la plupart du temps), vous devez désactiver globbing (
set -o noglob
/set -f
) et corriger$IFS
. Sinon, vous causerez également des vulnérabilités (comme l'exemple CGI de David Korn mentionné ci-dessus).Conclusion
En bref, laisser une variable (ou une substitution de commande ou une expansion arithmétique) sans mention de shells dans les shells peut être très dangereux, surtout dans les mauvais contextes, et il est très difficile de savoir quels sont ces mauvais contextes.
C'est l'une des raisons pour lesquelles c'est considéré comme une mauvaise pratique .
Merci d'avoir lu jusqu'ici. Si cela vous dépasse, ne vous inquiétez pas. On ne peut pas s'attendre à ce que tout le monde comprenne toutes les implications de l'écriture de son code de la façon dont il l'écrit. C'est pourquoi nous avons des recommandations de bonnes pratiques , afin qu'elles puissent être suivies sans nécessairement comprendre pourquoi.
(et si cela n’est pas encore évident, évitez d’écrire du code sensible à la sécurité dans des shells).
Et citez vos variables sur vos réponses sur ce site!
¹Dans
ksh93
etpdksh
et dérivés, le développement d'accolades est également effectué, sauf si la suppression est désactivée (dans le cas deksh93
versions jusqu'à ksh93u +, même lorsque l'braceexpand
option est désactivée).la source
[[
seulement l'ERS des comparaisons doit être cité:if [[ $1 = "$2" ]]; then
[[ $* = "$var" ]]
n'est pas la même chose que[[ "$*" = "$var" ]]
si le premier caractère de$IFS
n'est pas un espacebash
(et aussimksh
si$IFS
est vide mais dans ce cas, je ne suis pas sûr de ce qui$*
est égal à, devrais-je générer un bogue?)).foo='bar; rm *'
, non, ce ne sera pas le cas, mais le contenu du répertoire actuel sera répertorié, ce qui peut être considéré comme une divulgation d'informations.print $foo
inksh93
(oùprint
est le remplacementecho
qui résout certaines de ses lacunes) a une vulnérabilité d'injection de code bien que (par exemple avecfoo='-f%.0d z[0$(uname>&2)]'
) (vous avez réellement besoinprint -r -- "$foo"
.echo "$foo"
est toujours faux et non réparable (bien que généralement moins dommageable)).[Inspiré par cette réponse par cas .]
Mais si …?
Je ne peux pas dire ; cela échouera si est la chaîne vide.
grep "$ignorecase" other_grep_args
$ignorecase
Réponse:
Comme indiqué dans l'autre réponse, cela échouera encore si
IFS
contient un-
ou uni
. Si vous vous êtes assuré qu'ilIFS
ne contenait aucun caractère dans votre variable (et que vous êtes certain que votre variable ne contenait aucun caractère glob), cela est probablement sans danger.Mais il existe un moyen plus sûr (bien que ce soit un peu moche et peu intuitif): utiliser
${ignorecase:+"$ignorecase"}
. A partir de la spécification POSIX Shell Command Language , sous 2.6.2 Extension des paramètres ,Le truc ici, tel qu’il est, c’est que nous utilisons
ignorecase
comme leparameter
et"$ignorecase"
comme leword
. Donc${ignorecase:+"$ignorecase"}
moyenCela nous mène là où nous voulons aller: si la variable est définie sur la chaîne vide, elle sera «supprimée» (cette expression complète et convoluée ne sera évaluée à rien - pas même une chaîne vide), et si la variable a une valeur non -une valeur, nous obtenons cette valeur, citée.
Mais si …?
Réponse:
Vous pourriez penser que c'est un cas d'utilisationNon! Résistez à la tentation de penser même à utilisereval
.eval
ici.Encore une fois, si vous vous êtes assuré qu'il
IFS
ne contenait aucun caractère dans votre variable (à l'exception des espaces que vous souhaitez respecter), et que vous êtes sûr que votre variable ne contient aucun caractère glob, la réponse ci-dessus est probablement sûr.Mais si vous utilisez bash (ou ksh, zsh ou yash), il existe un moyen plus sûr: utilisez un tableau:
De bash (1) ,
Donc,
"${criteria[@]}"
développe (dans l'exemple ci-dessus) le zéro, deux ou quatre éléments ducriteria
tableau, chacun cité. En particulier, si aucune des conditions s n'est vraie, lecriteria
tableau n'a pas de contenu (comme défini par l'criteria=()
instruction) et est"${criteria[@]}"
évalué à rien (pas même une chaîne vide gênante).Cela devient particulièrement intéressant et compliqué lorsque vous utilisez plusieurs mots, dont certains sont des entrées dynamiques (utilisateur), que vous ne connaissez pas à l'avance, et peuvent contenir des espaces ou d'autres caractères spéciaux. Considérer:
Notez que
$fname
cite chaque fois qu'il est utilisé. Cela fonctionne même si l'utilisateur entre quelque chose commefoo bar
oufoo*
;"${criteria[@]}"
évalue à-name "foo bar"
ou-name "foo*"
. (N'oubliez pas que chaque élément du tableau est cité.)Les tableaux ne fonctionnent pas dans tous les shells POSIX; les tableaux sont un ksh / bash / zsh / yash-ism. Sauf que… il y a un tableau que tous les shells supportent: la liste d'arguments, aka
"$@"
. Si vous en avez terminé avec la liste d'arguments avec laquelle vous avez été appelé (par exemple, vous avez copié tous les «paramètres de position» (arguments) dans des variables, ou les avez autrement traités), vous pouvez utiliser la liste d'arguments comme un tableau:La
"$@"
construction (qui, historiquement, est arrivée en premier) a la même sémantique que - elle développe chaque argument (c'est-à-dire chaque élément de la liste d'arguments) en un mot séparé, comme si vous l'aviez saisi ."${name[@]}"
"$1" "$2" "$3" …
Extrait de la spécification POSIX Shell Command Language , sous 2.5.2 Paramètres spéciaux ,
Le texte intégral est quelque peu cryptique; le point clé est qu'il spécifie que
"$@"
doit générer des champs zéro lorsqu'il n'y a pas de paramètre de position. Note historique: lorsqu’il a"$@"
été introduit pour la première fois dans le shell Bourne (prédécesseur de bash) en 1979, il contenait un bogue qui"$@"
avait été remplacé par une seule chaîne vide en l’absence de paramètres de position; voir Que${1+"$@"}
signifie un script shell et en quoi diffère-t-il"$@"
? , Shell traditionnel Bourne famille , Qu'est-ce que${1+"$@"}
signifie ... et où est - il nécessaire? et"$@"
contre${1+"$@"}
.Les tableaux aident également à la première situation:
____________________
PS (csh)
Cela devrait aller de soi, mais pour le bénéfice des nouveaux venus: csh, tcsh, etc., ne sont pas des shells Bourne / POSIX. Ils sont une famille complètement différente. Un cheval de couleur différente. Un tout autre jeu de balle. Une race de chat différente. Oiseaux d'une autre plume. Et, plus particulièrement, une autre boîte de Pandore.
Une partie de ce qui a été dit sur cette page s’applique à csh; tels que: c’est une bonne idée de citer toutes vos variables à moins que vous n’ayez une bonne raison de ne pas le faire, et vous êtes sûr de savoir ce que vous faites. Mais, dans csh, chaque variable est un tableau - il se trouve que presque chaque variable est un tableau composé d’un seul élément et qu’elle se comporte comme une variable shell ordinaire dans les shells Bourne / POSIX. Et la syntaxe est terriblement différente (et je dis terriblement ). Donc, nous n'en dirons pas plus sur les obus de la famille csh ici.
la source
csh
, vous préférez utiliser plutôt$var:q
que"$var"
ce dernier ne fonctionne pas pour les variables contenant des caractères de nouvelle ligne (ou si vous souhaitez citer les éléments du tableau individuellement, plutôt que de les joindre avec des espaces dans un seul argument).bitrate="--bitrate 320"
fonctionne avec${bitrate:+$bitrate}
, etbitrate=--bitrate 128
ne fonctionnera pas${bitrate:+"$bitrate"}
car il interrompt la commande. Est-ce sécuritaire d'utiliser${variable:+$variable}
sans"
?$@
pour autre chose), ou si vous refusez simplement d'utiliser un tableau pour d'autres raisons, je vous renvoie vous à «comme indiqué dans l’autre réponse». … (Suite)${variable:+$variable}
sans"
) échouera si IFS contient-
,0
,2
,3
,a
,b
,e
,i
,r
out
.${bitrate:+$bitrate}
J'étais sceptique quant à la réponse de Stéphane, cependant il est possible d'abuser
$#
:ou $ ?:
Ce sont des exemples artificiels, mais le potentiel existe.
la source