42 votes

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

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

Je veux appeler le programme dans le shell bash et passer cette expression régulière en tant qu'argument de ligne de commande au programme (il y a é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 le bash. Ainsi, appeler

programme [abc]\_[x|y] unautreargument

ne fonctionne pas. Y a-t-il un moyen de passer l'expression en utilisant des caractères d'échappement ou des guillemets, etc. ?

(Appeler programme "[abc]\_[x|y] unautreargument" ne fonctionne pas non plus, car il interprète les deux arguments comme un seul.)

34voto

antichris Points 1118

Vous pouvez soit:

  1. Echapper chaque symbole spécial unique avec un antislash (comme dans \[abc\]_\[x\|y\]) ou
  2. Mettre l'argument entier entre guillemets (comme dans "[abc]_[x|y]").

EDIT: Comme certains l'ont souligné, mettre entre guillemets ne prévient pas l'expansion de variables ni la substitution de commandes. Donc si votre regex contient quelque chose qui peut être interprété par bash comme l'une de celles-ci, utilisez des simples quotes à la place.

33voto

Flimm Points 9047

Utilisez des apostrophes simples. Les apostrophes simples garantissent que aucun des caractères ne sont interprétés.

$ printf %s 'les espaces ne sont pas interprétés
ni les nouvelles lignes
ni les noms de variables $TESTING
ni les crochets [TESTING]
ni les caractères de pipe ou les symboles de redirection | > <
ni le point-virgule ;
ni les contre-obliques \a \b \c \\
la seule chose qui ne fonctionne pas est l'apostrophe simple elle-même
'

Il existe deux solutions si vous avez besoin d'intégrer une apostrophe simple :

$ printf '%s\n' '[ Ne t'inquiète pas, sois heureux! ]'
[ Don't worry, be happy! ]
$ printf '%s\n' '[ Ne t'\''inquiète pas, sois heureux! ]'
[ Don't worry, be happy! ]

7voto

decibel Points 341

Par man bash

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

Un anti-slash non cité (\) est le caractère d'échappement. Il préserve la valeur littérale du caractère suivant, à l'exception du . Si une paire \ apparaît et que l'anti-slash n'est pas lui-même cité, le \ est traité comme une continuation de ligne (c'est-à-dire qu'il est supprimé du flux d'entrée et effectivement ignoré).

Entourer les caractères de guillemets simples préserve la valeur littérale de chaque caractère entre les guillemets. Un guillemet simple ne peut pas apparaître entre des guillemets simples, même lorsqu'il est précédé d'un anti-slash.

Entourer les caractères de guillemets doubles préserve la valeur littérale de tous les caractères entre les guillemets, à l'exception de $, `, \ et, lorsque l'expansion de l'historique est activée, !. Les caractères $ et ` conservent leur signification spéciale entre guillemets doubles. L'anti-slash conserve sa signification spéciale uniquement s'il est suivi de l'un des caractères suivants : $, `, ", \ ou . Un guillemet double peut être cité entre des guillemets doubles en le précédant d'un anti-slash. Si l'expansion de l'historique est activée, elle sera effectuée sauf si un ! apparaissant entre guillemets doubles est échappé avec un anti-slash. L'anti-slash précédant le ! n'est pas supprimé.

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

Les mots de forme $'chaîne' sont traités spécialement. Le mot se développe en chaîne, les caractères échappés par un anti-slash étant remplacés comme spécifié par la norme ANSI C. Les séquences d'échappement par anti-slash, si elles sont présentes, sont décodées comme suit :

       **\\a**     alerte (cloche)
       **\\b**     retour en arrière
       **\\e**
       **\\E**     un caractère d'échappement
       **\\f**     saut de page
       **\\n**     nouvelle ligne
       **\\r**     retour chariot
       **\\t**     tabulation horizontale
       **\\v**     tabulation verticale
       **\\\\**     anti-slash
       **\\'**     guillemet simple
       **\\"**     guillemet double
       **\\**_nnn_   le caractère octet dont la valeur est la valeur octale _nnn_
              (un à trois chiffres)
       **\\x**_HH_   le caractère octet dont la valeur est la valeur hexadécimale _HH_
              (un ou deux chiffres hexadécimaux)
       **\\u**_HHHH_ le caractère Unicode (ISO/IEC 10646) dont la valeur est
              la valeur hexadécimale _HHHH_ (un à quatre chiffres hexadécimaux)
       **\\U**_HHHHHHHH_
              le caractère Unicode (ISO/IEC 10646) dont la valeur est
              la valeur hexadécimale _HHHHHHHH_ (un à huit chiffres hexadécimaux)
       **\\c**_x_    un caractère de contrôle-_x_

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

Une chaîne entre guillemets doubles précédée d'un signe dollar ($"chaîne") provoquera la traduction de la chaîne selon la locale actuelle. Si la locale actuelle est C ou POSIX, le signe dollar est ignoré. Si la chaîne est traduite et remplacée, le remplacement est entre guillemets doubles.

2voto

Dalroth Points 2468

Vous pouvez utiliser un backslash ( \ ) devant les caractères spéciaux pour les échapper comme ceci :

john@awesome:~ # echo \\&
&

2voto

Damian Powell Points 315

Bien que cela puisse ne pas être utile en tant qu'expression régulière, certaines séquences de caractères peuvent être interprétées comme des noms de variables Bash. Pour éviter que cela se produise et éviter qu'ils ne soient développés, utilisez des guillemets simples au lieu de guillemets doubles :

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

Citez chaque argument séparément (s'ils ont besoin d'être cités) afin 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]' autreargument)    # créer un tableau
param_array+=(encoreunautre)     # ajouter un autre élément au tableau
program "${param_array[@]}"   # utiliser les éléments du tableau comme arguments pour le programme

SistemesEz.com

SystemesEZ est une communauté de sysadmins où vous pouvez résoudre vos problèmes et vos doutes. Vous pouvez consulter les questions des autres sysadmins, poser vos propres questions ou résoudre celles des autres.

Powered by:

X