Dans Bash, lorsque vous spécifiez des arguments de ligne de commande pour une commande, quels caractères doivent être échappés?
Sont - ils limités aux métacaractères de Bash: l' espace, onglet,
|
, &
, ;
, (
, )
, <
et >
?
Dans Bash, lorsque vous spécifiez des arguments de ligne de commande pour une commande, quels caractères doivent être échappés?
Sont - ils limités aux métacaractères de Bash: l' espace, onglet,
|
, &
, ;
, (
, )
, <
et >
?
Réponses:
Les caractères suivants ont une signification particulière pour le shell lui-même dans certains contextes et peuvent devoir être échappés dans les arguments:
`
Contour (U + 0060 accent grave)~
Tilde (U + 007E)!
Point d'exclamation (U + 0021)#
Hachage (signe de numéro U + 0023)$
Signe dollar (U + 0024)&
Esperluette (U + 0026)*
Astérisque (U + 002A)(
Parenthèse gauche (U + 0028))
Parenthèse droite (U + 0029)
( ⇥
) Onglet (U + 0009){
Accolade gauche (U + 007B gauche ACCOLADE)[
Support carré gauche (U + 005B)|
Barre verticale (ligne verticale U + 007C)\
Barre oblique inverse (U + 005C Solidus inversé);
Point-virgule (U + 003B)'
Devis simple / Apostrophe (U + 0027)"
Devis double (U + 0022)↩
Nouvelle ligne (U + 000A)<
Moins de (U + 003C)>
Supérieur à (U + 003E)?
Point d'interrogation (U + 003F)
Espace (U + 0020) 1Certains de ces personnages sont utilisés pour plus de choses et dans plus d'endroits que celui que j'ai lié.
Il existe quelques cas d'angle qui sont explicitement facultatifs:
!
peut être désactivé avec set +H
, qui est la valeur par défaut dans les shells non interactifs.{
peut être désactivé avec set +B
.*
et ?
peut être désactivé avec set -f
ouset -o noglob
.=
Le signe égal (U + 003D) doit également être échappé si set -k
ouset -o keyword
est activé.Échapper à une nouvelle ligne nécessite des guillemets - les barres obliques inverses ne feront pas l'affaire. Tous les autres caractères répertoriés dans IFS auront besoin d'une gestion similaire. Vous n'avez pas besoin d'échapper ]
ou }
, mais vous ne devez échapper )
parce que c'est un opérateur.
Certains de ces personnages ont des limites plus strictes quant au moment où ils ont vraiment besoin de s'échapper que d'autres. Par exemple, a#b
c'est ok, mais a #b
c'est un commentaire, alors >
qu'il faudrait s'échapper dans les deux contextes. De toute façon, cela ne fait pas de mal de leur échapper de manière conservatrice, et c'est plus facile que de se souvenir des fines distinctions.
Si le nom de votre commande lui - même est un mot - clé shell ( if
, for
, do
) alors vous aurez besoin d'échapper ou de citer aussi. La seule intéressante de celles-ci est in
, car il n'est pas évident que c'est toujours un mot-clé. Vous n'avez pas besoin de le faire pour les mots clés utilisés dans les arguments, uniquement lorsque vous avez (stupidement!) Nommé une commande après l'un d'eux. Opérateurs Shell ( (
, &
, etc.) ont toujours besoin de citer , où qu'ils soient.
1 Stéphane a noté que tout autre caractère vierge à un octet de votre région doit également être échappé. Dans la plupart des environnements locaux sensibles, au moins ceux basés sur C ou UTF-8, ce ne sont que les espaces blancs ci-dessus. Dans certains environnements locaux ISO-8859-1, l'espace sans interruption U + 00A0 est considéré comme vide, y compris Solaris, les BSD et OS X (je pense à tort). Si vous avez affaire à un lieu inconnu arbitraire, cela peut inclure à peu près tout, y compris des lettres, alors bonne chance.
En théorie, un seul octet considéré comme vide pourrait apparaître dans un caractère multi-octets qui n'était pas vide, et vous n'auriez aucun moyen d'y échapper autre que de mettre le tout entre guillemets. Ce n'est pas une préoccupation théorique: dans un environnement local ISO-8859-1 d'en haut, cet A0
octet qui est considéré comme un blanc peut apparaître dans des caractères multi-octets comme UTF-8 encodé "à" ( C3 A0
). Pour gérer ces caractères en toute sécurité, vous devez les citer "à"
. Ce comportement dépend de la configuration locale dans l'environnement exécutant le script, pas celle dans laquelle vous l'avez écrit.
Je pense que ce comportement est brisé de plusieurs façons, mais nous devons jouer la main qui nous est distribuée. Si vous travaillez avec un jeu de caractères multi-octets non auto-synchronisé, le plus sûr serait de tout citer. Si vous êtes en UTF-8 ou C, vous êtes en sécurité (pour le moment).
!
lorsque l'expansion de l'historique csh est activée, généralement pas dans les scripts. [ ! -f a ]
ou find . ! -name...
bien. Cela est couvert par votre section sur les limites plus strictes, mais cela mérite peut-être d'être mentionné explicitement.
hash[foo"]"]=
, ${var-foo"}"}
, [[ "!" = b ]]
, [[ a = "]]" ]]
, les opérateurs de regexp pour [[ x =~ ".+[" ]]
. D' autres mots - clés que {
( if
, while
, for
...) devront être cité afin qu'ils ne sont pas reconnus comme tels ...
]
), donc je ne les énumère pas. Je ne pense pas qu'un mot-clé doive être cité en position d'argument.
Dans GNU Parallel, cela est testé et largement utilisé:
$a =~ s/[\002-\011\013-\032\\\#\?\`\(\)\{\}\[\]\^\*\<\=\>\~\|\; \"\!\$\&\'\202-\377]/\\$&/go;
# quote newline as '\n'
$a =~ s/[\n]/'\n'/go;
Il est testé bash
, dash
, ash
, ksh
, zsh
et fish
. Certains des personnages n'ont pas besoin d'être cités dans certaines (versions) des shells, mais ce qui précède fonctionne dans tous les shells testés.
Si vous voulez simplement une chaîne entre guillemets, vous pouvez la diriger vers parallel --shellquote
:
printf "&*\t*!" | parallel --shellquote
Pour une solution d'échappement légère en Perl, je suis le principe des guillemets simples. Une chaîne Bash entre guillemets simples peut avoir n'importe quel caractère, à l'exception de la guillemet simple elle-même.
Mon code:
my $bash_reserved_characters_re = qr([ !"#$&'()*;<>?\[\\`{|~\t\n]);
while(<>) {
if (/$bash_reserved_characters_re/) {
my $quoted = s/'/'"'"'/gr;
print "'$quoted'";
} else {
print $_;
}
}
Exemple d'exécution 1:
$ echo -n "abc" | perl escape_bash_special_chars.pl
abc
Exemple d'exécution 2:
echo "abc" | perl escape_bash_special_chars.pl
'abc
'
Exemple d'exécution 3:
echo -n 'ab^c' | perl escape_bash_special_chars.pl
ab^c
Exemple d'exécution 4:
echo -n 'ab~c' | perl escape_bash_special_chars.pl
'ab~c'
Exemple d'exécution 5:
echo -n "ab'c" | perl escape_bash_special_chars.pl
'ab'"'"'c'
echo 'ab'"'"'c'
ab'c