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


38

J'ai un fichier qui a "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 d'un jeton inattendu `('

et

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

Réponses:


54

Vous devez mettre l'expression entre guillemets. L'erreur que vous recevez est le résultat de l'interprétation (que bash fait du 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 à la |, (et ). Notez que nous utilisons des guillemets simples ici. Bash traite spécialement les barres obliques inverses entre guillemets doubles.

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

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

$ grep 'then\|there' x.x

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

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

3
Voir aussi grep $'then\nthere'et grep -e then -e there. Notez que ce \|n'est pas la norme dans les BRE. Le reste est. Bash traite antislashs spécialement dans des guillemets doubles seulement avant ", $, \ , `et retour à la ligne.
Stéphane Chazelas

1
Quel est le but de x.x?
alex

7

Juste un petit ajout, 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


2

Les éléments documentés sous REGULAR EXPRESSIONS dans la page de manuel (ou du moins, my) s’appliquent réellement aux expressions rationnelles étendues ;

grep comprend trois versions différentes de la syntaxe des expressions rationnelles: “basic”, “extended” et “perl”. Dans GNU grep, il n'y a pas de différence de fonctionnalité 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 rationnelles de base sont résumées par la suite.

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

grep "(then|there)" x.x

Parce que (de la page de man à nouveau):

Expressions régulières basiques vs étendues

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

Donc vous pouvez aussi utiliser:

grep "then\|there" x.x

Puisque les parenthèses sont superflues dans ce cas.


0

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: echoet 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;, echoet 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 echon'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 tokendé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|thereet 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

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.