La simplicité élégante de Bash semble se perdre dans son énorme page de manuel.
En plus des excellentes solutions ci-dessus, j'ai pensé essayer de vous donner une triche sur la façon dont bash analyse et interprète les déclarations . Ensuite, en utilisant cette feuille de route, je vais analyser les exemples présentés par le questionneur pour vous aider à mieux comprendre pourquoi ils ne fonctionnent pas comme prévu.
Remarque: les lignes de script shell sont utilisées directement. Les lignes d'entrée typées sont d'abord enrichies en historique.
Chaque ligne de bash est d'abord symbolisée , ou autrement dit découpée en ce que l'on appelle des jetons . (La création de jetons a lieu avant toutes les autres extensions, notamment l'accolade, le tilde, le paramètre, la commande, l'arithmétique, le processus, le fractionnement des mots et le développement du nom de fichier.)
Un jeton signifie ici une partie de la ligne d'entrée séparée (délimitée) par l'un de ces méta-caractères spéciaux:
space, - White space...
tab,
newline,
‘<’, - Redirection & piping...
‘|’,
‘>’
‘&’, - And/Both < | > | >> .or. &<file descriptor>
‘;’, - Command termination
‘(’, - Subshell, closed by - ‘)’
Bash utilise beaucoup d'autres caractères spéciaux, mais seuls ces 10 produisent les jetons initiaux.
Cependant, étant donné que ces méta-caractères doivent parfois aussi être utilisés dans un jeton, il doit exister un moyen de supprimer leur signification particulière. Ceci s'appelle s'échapper. L'échappement se fait soit en citant une chaîne d'un ou de plusieurs caractères (c.-à 'xx..'
- d . "xx.."
), Soit en préfixant un caractère individuel avec une barre oblique inversée (c.-à-d \x
.). (C'est un peu plus compliqué que cela parce que les guillemets doivent également être cités et que les guillemets doubles ne citent pas tout, mais cette simplification conviendra pour le moment.)
Ne confondez pas bash quotes avec l'idée de citer une chaîne de texte, comme dans d'autres langues. Ce qui est entre guillemets dans bash ne correspond pas à des chaînes, mais plutôt à des sections de la ligne d'entrée dans lesquelles des méta-caractères ont été échappés afin de ne pas délimiter les jetons.
Notez qu'il y a une différence importante entre '
, et "
, mais c'est pour un autre jour.
Les méta-caractères non échappés restants deviennent alors des séparateurs de jetons.
Par exemple,
$ echo "x"'y'\g
xyg
$ echo "<"'|'\>
<|>
$ echo x\; echo y
x; echo y
Dans le premier exemple, il y a deux jetons produits par un délimiteur d'espace: echo
et xyz
.
De même dans le 2ème exemple.
Dans le troisième exemple est le point - virgule échappé, donc il y a 4 jetons produits par un séparateur d'espace, echo
, x;
, echo
et y
. Le premier jeton est ensuite exécuté en tant que commande et prend les trois prochains jetons en entrée. Notez que le 2ème echo
n'est pas exécuté.
La chose importante à retenir est que les premiers regards pour les personnages bash Évasion ( '
, "
et \
), et cherche ensuite délimiteurs méta-caractères unescaped, dans cet ordre.
Sinon, ces 10 caractères spéciaux servent de token
délimiteurs. Certains d'entre eux ont également une signification supplémentaire, mais ils sont avant tout des délimiteurs symboliques.
Ce que grep attend
Dans l'exemple ci - dessus grep a besoin de ces jetons, grep
, string
, filename
.
Le premier essai de la question était:
$ grep (alors | il) xx
Dans ce cas (
, )
et |
sont des caractères meta unescaped et ainsi servent à diviser l'entrée en ces jetons: grep
, (
, then
, |
, there
, )
et x.x
. grep veut voir grep
, then|there
et x.x
.
Le deuxième essai de la question était:
grep "(alors | il)" "xx
Ce tokenizes dans grep
, (then|there)
, x.x
. Vous pouvez voir cela si vous remplacez grep par echo:
echo "(alors | il))" xx
(alors | il) xx