J'ai une application qui prend comme attributs d'entrée des guillemets doubles intégrés dans des guillemets simples. Prenez par exemple cette bonne commande:
command -p 'cluster="cl1"'
Afin de l'automatiser, j'ai créé un fichier bash en utilisant $CLUSTER
comme variable. Comment devrait être ma commande? En d'autres termes, que dois-je mettre à la place de cl1?
Veuillez noter que si j'ai modifié la commande ci-dessus, elle ne sera pas acceptée. Par exemple: command -p "cluster=cl1"
n'est pas accepté
CLUSTER='"cl1"'; command -p "cluster=$CLUSTER"
cli
sans guillemets dans laCLUSTER
variable):CLUSTER='cl1'; command -p 'cluster="'"$CLUSTER"'"'
Réponses:
Il semble que votre commande définisse peut-être des variables d'environnement basées sur des arguments donnés sur la ligne de commande. Il se peut que vous puissiez faire:
... et lui a défini son environnement lors de l'invocation.
Sinon, les guillemets shell délimitent généralement les arguments ou échappent à d'autres caractères shell spéciaux de l'interprétation shell. Vous pouvez contenir (et donc échapper) différents types de citations shell dans d'autres types en fonction de différentes règles:
"''''"
- une chaîne entre guillemets peut contenir n'importe quel nombre de guillemets."\""
- une\
barre oblique inversée peut échapper à un"
guillemet"
doux dans une chaîne entre guillemets.\\
barre oblique inversée s'échappe également, le\$
jeton d'expansion et les\n
lignes électroniques comme indiqué ci-dessous, mais est autrement traité littéralement."${expand} and then some"
- une chaîne entre guillemets peut contenir une$
expansion interprétée du shell .'"\'
- une'
chaîne entre guillemets peut contenir tout caractère autre qu'un'
guillemet.\
- une barre oblique inverse sans guillemets échappe à tout caractère suivant pour une interprétation littérale - même une autre barre oblique inverse - à l'exception d'une ligne\n
électronique.\\n
cas de ligne électronique, la\
barre oblique inverse et la ligne\n
électronique sont complètement supprimées de la commande interprétée résultante.${parameter+expand "$parameter"}
- les guillemets résultant d'une expansion du shell ne servent presque jamais de marqueurs de délimitation à l'exception de quelques cas particuliers. Je ne m'aventurerai pas à les décrire davantage ici.Je trouve étrange que toute application interprète des guillemets dans ses arguments de ligne de commande. Une telle pratique n'a pas beaucoup de sens en ce que - pour les coquilles, au moins - le but principal d'une citation est généralement de délimiter un argument. À l'invocation, cependant, les arguments sont toujours déjà délimités par des
\0NUL
caractères et une citation ne peut donc pas être très utile.Même un shell ne prend généralement la peine d'interpréter les guillemets dans l'un de ses arguments d'invocation que lorsqu'il est appelé avec un
-c
commutateur - ce qui indique que son premier opérande est en fait un script shell qu'il doit exécuter lors de l'invocation. C'est un cas d' entrée évaluée deux fois .Cela dit, vous pouvez faire un certain nombre de choses pour passer des guillemets littéraux via des arguments sur la ligne de commande. Par exemple:
Comme je l'ai noté dans un commentaire auparavant, vous pouvez contenir les
"
guillemets dans une extension qui est elle-même"
citée.Vous pouvez échapper à
"
avec une\
barre oblique inverse dans la"
chaîne entre guillemets.Vous pouvez alterner et concaténer les styles de devis pour arriver au résultat final souhaité comme le note @jimmij ci-dessus .
Vous pouvez désactiver à la fois la génération et la
$IFS
division des noms de fichiers - évitant ainsi la nécessité de citer le$expansion
tout - et donc uniquement les guillemets. C'est probablement exagéré.Enfin, il existe un autre type de shell-quote qui pourrait être utilisé. Comme je l'ai noté précédemment, la
sh -c "$scriptlet"
forme d'invocation du shell est souvent utilisée pour fournir un script de shell sur la ligne de commande. Lorsque cela$scriptlet
se complique - comme lorsque les guillemets doivent contenir d'autres guillemets - il peut souvent être avantageux d'utiliser un document ici et à lash -s
place - où le shell est spécifiquement chargé d'attribuer tous les opérandes suivants aux paramètres de position comme il le ferait dans un-c
cas et pourtant de prendre également son scriptstdin
.Si votre commande doit interpréter les guillemets de cette manière, je considérerais qu'il vaut mieux qu'elle puisse le faire dans une entrée de fichier. Par exemple:
Si vous ne citez pas le délimiteur d'un,
<<here-document
alors tout son contenu est traité presque exactement comme il l'a été entre"
guillemets - sauf que les"
guillemets eux-mêmes ne sont pas traités spécialement. Et donc si nous exécutons ce qui précède à lacat
place:... ça imprime ...
la source
Comme l'a écrit mikeserv :
« Guillemets » chaque littéral qui contient des espaces / métacaractères et chaque extension:
"$var"
,"$(command "$var")"
,"${array[@]}"
,"a & b"
. Utilisez'single quotes'
pour le code ou littéral$'s: 'Costs $5 US'
,ssh host 'echo "$HOSTNAME"'
. Voirhttp://mywiki.wooledge.org/Quotes
http://mywiki.wooledge.org/Arguments
http://wiki.bash-hackers.org/syntax/words
la source
"
caractères - seuls le premier et le dernier devraient être suffisants. Le vrai problème ici est que votre application interprète les citations dans un argument. L'interprétation d'une citation dans un argument n'est presque jamais une bonne idée car une citation ne doit être qu'un moyen de délimiter un argument - et à l'invocation, cette délimitation est gérée par\0NUL
s dans tous les cas. Il existe probablement un meilleur moyen de transmettre les informations que vous souhaitez à l'application? Comme uncommand --'script=/path/to/some/file'
ou quelque chose?