web-dev-qa-db-fra.com

bash: comment passer des arguments en ligne de commande contenant des caractères spéciaux

J'ai moi-même écrit un programme linux program qui nécessite une expression régulière en entrée.

Je souhaite appeler le programme dans le shell bash et lui transmettre cette expression régulière en tant qu'argument de ligne de commande (il existe également d'autres arguments de ligne de commande). Une expression régulière typique ressemble à

[abc]\_[x|y]

Malheureusement, les caractères [, ] et | sont des caractères spéciaux dans bash. Ainsi, en appelant

program [abc]\_[x|y] anotheragument

ne fonctionne pas. Existe-t-il un moyen de passer l'expression en utilisant une sorte de caractère d'échappement, de guillemets, etc.?

(L'appel de program "[abc]\_[x|y] anotheragument" ne fonctionne pas non plus, car il interprète les deux arguments comme un seul.)

29
Christian

Tu peux soit

  1. Echappez chaque symbole spécial avec une barre oblique inverse (comme dans \[abc\]_\[x\|y\]) ou
  2. Citez l'argument entier en double (comme dans "[abc]_[x|y]").

EDIT: Comme certains l’ont souligné, la suppression des doublons n’empêche pas le développement de variables ni la substitution de commandes. Par conséquent, si votre expression rationnelle contient quelque chose qui peut être interprété par bash comme l'un de ceux-ci, utilisez plutôt des guillemets simples .

24
U-D13

Utilisez des guillemets simples. Les guillemets simples garantissent qu'aucun des caractères n'est interprété.

$ printf %s 'spaces  are  not  interpreted away
neither are new lines
nor variable names $TESTING
nor square brackets [TESTING]
nor pipe characters or redirection symbols | > <
nor the semicolon ;
nor backslashes \a \b \c \\
the only thing that does not work is the single quote itself
'

Il existe deux solutions si vous devez intégrer un seul devis:

$ printf '%s\n' '[ Don'"'"'t worry, be happy! ]'
[ Don't worry, be happy! ]
$ printf '%s\n' '[ Don'\''t worry, be happy! ]'
[ Don't worry, be happy! ]
24
Flimm

Par man bash

Il existe trois mécanismes de guillemets: le caractère d'échappement , les guillemets simples et les guillemets doubles.

Une barre oblique inverse non citée (\) est le caractère d'échappement . Il conserve la valeur littérale du caractère suivant, à l'exception de <newline>. Si une paire \ <nouvelle ligne> apparaît et que la barre oblique inverse n'est pas elle-même citée, la \ <nouvelle ligne> est traitée comme une continuation de ligne ( (c’est-à-dire qu’il est supprimé du flux d’entrée et effectivement ignoré).

Le fait de placer des caractères entre guillemets simples préserve la valeur littérale de chaque caractère entre guillemets. Un seul guillemet ne peut pas apparaître entre guillemets, même s'il est précédé d'une barre oblique inverse.

Le fait de placer des caractères entre guillemets doubles préserve la valeur littérale de tous les caractères compris entre guillemets, à l'exception de $ , `, \ et, lorsque l'extension de l'historique est activée, ! . Les caractères $ et ` conservent leur signification particulière entre guillemets. La barre oblique inverse ne conserve sa signification particulière que si elle est suivie de l’un des caractères suivants: $ , `, " , \ ou <nouvelle ligne> . Un guillemet double peut être cité entre guillemets doubles en le faisant précéder d'une barre oblique inverse. Si activé, le développement de l'historique sera exécuté à moins qu'un ! figurant entre guillemets ne soit échappé à l'aide d'une barre oblique inverse. La barre oblique inverse précédant le ! n'est pas supprimée.

Les paramètres spéciaux * et @ ont une signification particulière entre guillemets (voir PARAMÈTRES ci-dessous) .

Mots de la forme $ 'chaîne' sont traités spécialement. Le mot se développe en chaîne, avec les caractères d'échappement avec une barre oblique inversée remplacés comme spécifié par la norme ANSI C. Les séquences d'échappement de barre oblique inverse, le cas échéant, sont décodées comme suit:

\une     alerte (cloche) 
 \ b     retour arrière 
 \ e\ E     un caractère d'échappement 
 \F     formulaire d'alimentation 
 \ n     nouvelle ligne
 \ r     retour chariot 
 \ t     onglet horizontal 
 \ v     onglet vertical 
 \\     backslash 
 \ '     simple citation
 \ "     double citation
 \nnn   le caractère de huit bits dont la valeur est la valeur octale nnn
 (un à trois chiffres) 
 \XHH   le caractère de huit bits dont la valeur est la valeur hexadécimale HH
 (un ou deux chiffres hexadécimaux) 
 \ uHHHH le caractère Unicode (ISO/IEC 10646) dont la valeur est 
 la valeur hexadécimale HHHH (un à quatre chiffres hexadécimaux) 
 \ UHHHHHHHH
 le caractère Unicode (ISO/IEC 10646) dont la valeur est 
 la valeur hexadécimale HHHHHHHH (un à huit chiffres hexadécimaux) 
 \ cx    un contrôlex personnage

Le résultat étendu est indiqué entre guillemets simples, comme si le signe dollar n'avait pas été présent.

Une chaîne entre guillemets précédée d’un signe dollar ($ "chaîne") entraînera la traduction de la chaîne en fonction des paramètres régionaux actuels. Si les paramètres régionaux actuels sont C ou POSIX, le signe dollar est ignoré. Si la chaîne est traduite et remplacée, le remplacement est cité en double.

6
Evan Carroll

Vous pouvez utiliser une barre oblique inverse (\) devant les caractères spéciaux pour les échapper de la manière suivante:

john @ awesome: ~ # echo\& 
 &
2
John T

Bien que cela puisse ne pas être utile en tant que regex, certaines séquences de caractères peuvent être interprétées comme des noms de variables Bash. Pour éviter cela et éviter de les développer, utilisez des guillemets simples au lieu de guillemets doubles:

program '[abc]_[x|y]' anotherargument

Citez chaque argument séparément (s'ils ont besoin de citer) pour qu'ils soient interprétés comme des arguments indépendants. Vous pouvez également utiliser des tableaux dans certains cas:

param_array=('[abc]_[x|y]' anotherargument)    # create an array
param_array+=(yetanother)     # append another element to the array
program "${param_array[@]}"   # use the array elements as arguments to program
2
Dennis Williamson
program "[abc]_[x|y]"
program "[abc]_[x|y]" anotherargument
1
Witek

D'où vient le motif? Est-ce fixe ou d'un utilisateur? Est-ce l'utilisateur qui appelle le script sur le système local ou une personne distante?

Vous utilisez des guillemets pour envelopper les données afin d'empêcher le shell de les interpréter. Il y a deux options:

  1. Les guillemets doubles, qui permettent encore une certaine interprétation ($ expand et `backticks`)
  2. Guillemets simples, qui passent tout littéralement

Étant donné que $ est un caractère valide dans les expressions rationnelles (fin de ligne/tampon), vous souhaiterez probablement utiliser des guillemets simples pour contenir l’expression rationnelle, à moins que vous ne la stockiez dans une variable. Si vous prenez des données arbitraires d'une personne non fiable, vous devrez remplacer ' par '"'"', puis insérer des guillemets simples.

Notez que [abc]_[x|y] semble correspondre à x ou y, alors qu’il correspond à l’un des trois caractères xy|. Les crochets correspondent aux caractères de - pour les plages et uniquement ^ au début de la négation. Donc, [abc]_(x|y) pourrait être ce que vous vouliez dire, et les parenthèses sont les caractères spéciaux de Shell. Les crochets ne sont pas spéciaux de Shell, ils semblent juste comme ils le sont. Les doubles crochets [[ ... ]] sont spéciaux.

0
Phil P

Les échapper devrait bien fonctionner:

  programm \[abc\]_\[x\|y\]
0
Bobby