web-dev-qa-db-fra.com

Comment puis-je grep pour ceci ou cela (2 choses) dans un fichier?

J'ai un fichier qui contient "alors" et "là".

Je peux

$ grep "then " x.x
x and then some
x and then some
x and then some
x and then some

et je peux

$ grep "there " x.x
If there is no blob none some will be created

Comment puis-je rechercher les deux en une seule opération? j'ai essayé

$ grep (then|there) x.x

-bash: erreur de syntaxe près du jeton inattendu `('

et

grep "(then|there)" x.x
durrantm.../code
# (Nothing)
44
Michael Durrant

Vous devez mettre l'expression entre guillemets. L'erreur que vous recevez est le résultat de bash interprétant le ( comme caractère spécial.

En outre, vous devez indiquer à grep d'utiliser des expressions régulières étendues.

$ grep -E '(then|there)' x.x

Sans expressions régulières étendues, vous devez échapper au |, (, et ). Notez que nous utilisons des guillemets simples ici. Bash traite spécialement les contre-obliques entre guillemets doubles.

$ grep '\(then\|there\)' x.x

Le regroupement n'est pas nécessaire dans ce cas.

$ grep 'then\|there' x.x

Il serait nécessaire pour quelque chose comme ça:

$ grep 'the\(n\|re\)' x.x
60
user26112

Juste un addenda rapide, la plupart des versions ont une commande appelée egrep qui est juste grep avec -E. Personnellement, j'aime beaucoup mieux taper

egrep "i(Pod|Pad|Phone)" access.log

Que d'utiliser grep -E

7
Trausti Thor

Les informations documentées sous REGULAR EXPRESSIONS dans la page de manuel (ou du moins, ma) sont en fait pour regexps étendues ;

grep comprend trois versions différentes de la syntaxe des expressions régulières: "de base", "étendu" et "Perl". Dans GNU grep, il n'y a pas de différence de fonctionnalité disponible entre les syntaxes de base et étendues. Dans d'autres implémentations, les expressions régulières de base sont moins puissantes. La description suivante s'applique aux expressions régulières étendues; les différences pour les expressions régulières de base sont résumées par la suite.

Mais grep ne les utilise pas par défaut - vous avez besoin du -E commutateur:

grep "(then|there)" x.x

Parce que (à partir de la page de manuel):

Expressions régulières de base et étendues

Dans les expressions régulières de base, les méta-caractères?, +, {, |, (Et) perdent leur signification spéciale; utilisez plutôt les versions avec barre oblique inversée\?, +, {,\|, (et).

Vous pouvez donc également utiliser:

grep "then\|there" x.x

Puisque les parenthèses sont superflues dans ce cas.

2
goldilocks

L'élégante simplicité de Bash semble se perdre dans son immense page de manuel.

En plus des excellentes solutions ci-dessus, j'ai pensé essayer de vous donner une feuille de triche sur comment bash analyse et interprète les instructions. 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 saisies sont d'abord développées dans l'historique.

Chaque ligne bash est d'abord tokenisée, ou en d'autres termes coupée en ce qu'on appelle tokens. (La tokenisation se produit avant toutes les autres extensions, y compris l'accolade, le tilde, le paramètre, la commande, l'arithmétique, le processus, le fractionnement de Word et l'expansion 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 de nombreux autres caractères spéciaux, mais seuls ces 10 produisent les jetons initiaux.

Cependant, parce que ces méta-caractères doivent parfois être utilisés dans un jeton, il doit y avoir un moyen d'enlever leur signification particulière. Cela s'appelle s'échapper. L'échappement se fait soit en citant une chaîne d'un ou plusieurs caractères, (c'est-à-dire 'xx..', "xx.."), ou en préfixant un caractère individuel avec une barre oblique inverse (par exemple \x). (C'est un peu plus compliqué que cela parce que les guillemets doivent également être cités, et parce que les guillemets doubles ne citent pas tout, mais cette simplification fera l'affaire pour l'instant.)

Ne confondez pas les citations bash avec l'idée de citer une chaîne de texte, comme dans d'autres langues. Ce qui se trouve entre les guillemets en bash ne sont pas des chaînes, mais plutôt des sections de la ligne d'entrée qui ont des méta-caractères échappés afin de ne pas délimiter les jetons.

Remarque, il existe une différence importante entre ', et ", mais c'est pour un autre jour.

Les méta-caractères restants non échappés 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 existe 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, le point-virgule est échappé, il y a donc 4 jetons produits par un délimiteur d'espace, echo, x;, echo et y. Le premier jeton est ensuite exécuté en tant que commande et prend les trois jetons suivants en entrée. Notez que le 2ème echo n'est pas exécuté.


La chose importante à retenir est que bash recherche d'abord les caractères qui s'échappent (', ", et \), puis recherche les délimiteurs de méta-caractères non échappés, dans cet ordre.

S'ils ne sont pas échappés, ces 10 caractères spéciaux servent de délimiteurs token. Certains d'entre eux ont également une signification supplémentaire, mais ce 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 | là) x.x

Dans ce cas (, ) et | sont des méta caractères non échappés et servent donc à 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 "(puis | là)" x.x

Cela symbolise en grep, (then|there), x.x. Vous pouvez voir ceci si vous échangez grep pour écho:

echo "(puis | là)" x.x
(puis | là) x.x

0
Elliptical view