Cette question n'est pas sur la façon d'écrire un littéral de chaîne correctement échappé. Je n'ai trouvé aucune question connexe qui ne concerne pas comment échapper des variables pour une consommation directe dans un script ou par d'autres programmes.
Mon objectif est de permettre à un script de générer d'autres scripts. En effet, les tâches dans les scripts générés s'exécuteront de 0 à n fois sur une autre machine, et les données à partir desquelles elles sont générées peuvent changer avant d'être exécutées (à nouveau), de sorte que les opérations directement, sur un réseau ne fonctionne pas.
Étant donné une variable connue qui peut contenir des caractères spéciaux tels que des guillemets simples, je dois l'écrire comme un littéral de chaîne complètement échappé, par exemple une variable foo
contenant bar'baz
devrait apparaître dans le script généré comme:
qux='bar'\''baz'
qui serait écrit en ajoutant "qux=$foo_esc"
aux autres lignes de script. Je l'ai fait en utilisant Perl comme ceci:
foo_esc="'`perl -pe 's/('\'')/\\1\\\\\\1\\1/g' <<<"$foo"`'"
mais cela semble exagéré.
Je n'ai pas réussi à le faire avec bash seul. J'ai essayé de nombreuses variantes de celles-ci:
foo_esc="'${file//\'/\'\\\'\'}'"
foo_esc="'${file//\'/'\\''}'"
mais soit des barres obliques supplémentaires apparaissent dans la sortie (quand je le fais echo "$foo"
), soit elles provoquent une erreur de syntaxe (en attendant des entrées supplémentaires si elles sont effectuées à partir du shell).
alias
et / ouset
assez universellementalias "varname=$varname" varname
ouvar=value set
Réponses:
Bash a une option d'extension de paramètre pour exactement ce cas :
Donc dans ce cas:
Ceci est pris en charge dans Bash 4.4 et versions ultérieures. Il existe également plusieurs options pour d'autres formes d'extension et pour générer spécifiquement des instructions d'affectation complètes (
@A
).la source
bad substitution
."${foo:q}"
."${foo@Q}"
travaux!Bash fournit un
printf
spécificateur de%q
format intégré , qui effectue l'échappement du shell pour vous, même dans les anciennes versions (<4.0) de Bash:Cette astuce peut également être utilisée pour renvoyer des tableaux de données à partir d'une fonction:
Notez que le Bash
printf
intégré est différent de l'printf
utilitaire fourni avec la plupart des systèmes d'exploitation de type Unix. Si, pour une raison quelconque, laprintf
commande appelle l'utilitaire au lieu du module intégré, vous pouvez toujours l'exécuter à labuiltin printf
place.la source
'Ne'\''er do well'
, etc., c'est-à-dire des citations incluses dans la sortie.[[ 'Ne'\''er do well' == Ne\'er\ do\ well ]] && echo 'equivalent!'
fera échoequivalent!
'hello'
entraîne une valeur incorrecte''\''hello''
, qui a une chaîne vide de début inutile (les deux premiers guillemets simples) et une guillemet simple de fin inappropriée.$'escape-these-chars'
est la fonction de citation ANSI-C de Bash qui provoque l' échappement de tous les caractères de la chaîne spécifiée. Ainsi, pour créer facilement un littéral de chaîne qui contient une nouvelle ligne dans le nom de fichier (par exemple$'first-line\nsecond-line')
, utiliser\n
dans cette construction.Je suppose que je n'ai pas RTFM. Cela peut se faire comme suit:
echo "$foo_esc"
Donne ensuite l'attendu'bar'\''baz'
Comment je l'utilise réellement avec une fonction:
Modifier cela pour utiliser la
printf
solution intégrée de Dejay:la source
Il existe plusieurs solutions pour citer une valeur var:
alias
Dans la plupart des shells (où l'alias est disponible) (sauf csh, tcsh et probablement d'autres comme csh):
Oui, cela fonctionne dans de nombreuses
sh
coquilles comme le tableau de bord ou la cendre.mettre
également dans la plupart des coquilles (encore une fois, non csh):
typeset
Dans quelques coquilles (ksh, bash et zsh au moins):
Exporter d'
abord faire:
Ensuite, utilisez:
ksh
export -p | grep 'qux='
bashexport -p | grep 'qux='
zsh
export -p qux
citer
bash
echo "${qux@Q}"
zsh
echo "${(qq)qux}"
# de un à quatre q peut être utilisé.la source
grep
avecexport
ouset
peuvent briser sur les variables contenant caractère de nouvelle ligne.