Je veux trouver toutes les lignes dans plusieurs fichiers qui correspondent à l'un des deux modèles. J'ai essayé de trouver les motifs que je cherchais en tapant
grep (foo|bar) *.txt
mais le shell interprète le |
comme un tuyau et se plaint quand ce bar
n'est pas un exécutable.
Comment puis-je grep pour plusieurs modèles dans le même ensemble de fichiers?
Réponses:
Tout d'abord, vous devez protéger le motif de l'expansion par le shell. Le moyen le plus simple de le faire est de mettre des guillemets simples autour. Les guillemets simples empêchent toute expansion entre eux (y compris les barres obliques inverses); la seule chose que vous ne puissiez pas faire est d'avoir des guillemets simples dans le motif.
Si vous avez besoin d'un seul guillemet, vous pouvez l'écrire comme
'\''
suit (littéral de chaîne de fin, citation littérale, littéral de chaîne ouverte).Deuxièmement, grep prend en charge deux syntaxes pour les modèles. L'ancienne syntaxe par défaut ( expressions régulières de base ) ne prend pas en charge l'
|
opérateur alternance ( ), bien que certaines versions l'aient comme extension, mais elle est écrite avec une barre oblique inverse.La méthode portable consiste à utiliser la syntaxe la plus récente, les expressions régulières étendues . Vous devez passer l'
-E
option pourgrep
le sélectionner. Sous Linux, vous pouvez également taper à laegrep
place degrep -E
(sur d’autres serveurs, vous pouvez en faire un alias).Une autre possibilité lorsque vous recherchez simplement plusieurs modèles (par opposition à la création d'un modèle complexe utilisant la disjonction) consiste à transmettre plusieurs modèles à
grep
. Vous pouvez le faire en précédant chaque motif avec l'-e
option.la source
fgrep
ougrep -F
, pour les petits motifs, la différence sera négligeable, mais à mesure qu'ils s'allongent, les avantages commencent à se manifester ...grep -F
bénéfice réel en termes de performances dépend de l'implémentation de grep: certains d'entre eux appliquent quand même le même algorithme, de sorte que cela ne-F
fait de différence que pour le temps passé à analyser le motif et non pour le temps de recherche. GNU grep n’est pas plus rapide avec-F
, par exemple (il a aussi un bogue quigrep -F
ralentit les locales multi-octets - le même motif constant avecgrep
est en réalité nettement plus rapide!). D'autre part, BusyBox grep tire profit-F
des fichiers volumineux.egrep
est antérieure àgrep -E
. Ce n'est pas spécifique à GNU (cela n'a certainement rien à voir avec Linux). En fait, vous trouverez toujours des systèmes comme Solaris où la configuration par défautgrep
ne prend toujours pas en charge-E
.ou
citant de manière sélective la page de manuel de gnu-grep:
(...)
Au début, je n'ai pas lu plus loin, alors je n'ai pas reconnu les différences subtiles:
J'ai toujours utilisé egrep et inutilement parens, parce que j'ai appris des exemples. Maintenant j'ai appris quelque chose de nouveau. :)
la source
Comme dit TC1,
-F
semble être une option utilisable:la source
Tout d'abord, vous devez utiliser des guillemets pour les caractères spéciaux. Deuxièmement, même ainsi,
grep
ne comprendra pas directement l’alternance; vous devrez utiliseregrep
, ou (avec GNUgrep
uniquement)grep -E
.(Les parenthèses sont inutiles, sauf si l'alternance fait partie d'une regex plus grande.)
la source
grep -E
est plus standard queegrep
.Si vous n'avez pas besoin d'expressions régulières, il est beaucoup plus rapide d'utiliser
fgrep
ougrep -F
avec plusieurs paramètres -e, comme ceci:fgrep
(alternativementgrep -F
) est beaucoup plus rapide que grep normal car il recherche des chaînes fixes au lieu d'expressions régulières.la source
fgrep
est déconseillée.Vous pouvez essayer la commande ci-dessous pour obtenir le résultat:
la source
Un moyen peu coûteux et joyeux de rechercher plusieurs motifs:
la source
-f
option de grep prend un fichier avec plusieurs modèles. Au lieu de créer un fichier temporaire (que vous pourriez oublier de supprimer par la suite), utilisez simplement le processus de substitution du shell:grep -f <(echo foo; echo bar) *.txt
Pipe (
|
) est un caractère spécial dans le shell, il doit donc être échappé (\|
) ou cité selon manual (man bash
):Voir: Quels personnages doivent être échappés dans Bash?
Voici quelques exemples (utilisant des outils non encore mentionnés):
Utilisant
ripgrep
:rg "foo|bar" *.txt
rg -e foo -e bar *.txt
Utilisant
git grep
:git grep --no-index -e foo --or -e bar
Remarque: Il prend également en charge les expressions booléennes telles que
--and
,--or
et--not
.Pour un fonctionnement AND par ligne, voir: Comment exécuter grep avec plusieurs modèles AND?
Pour une opération AND par fichier, voir: Comment vérifier si plusieurs chaînes ou expressions rationnelles existent dans un fichier?
la source
J'avais des journaux d'accès où les dates étaient bêtement formatées: [30 / Jun / 2013: 08: 00: 45 +0200]
Mais je devais l'afficher comme: 30 / Jun / 2013 08:00:45
Le problème est que, en utilisant "OU" dans mon instruction grep, je recevais les deux expressions de correspondance sur deux lignes distinctes.
Voici la solution:
la source
TL; DR: si vous voulez faire plus de choses après l’appariement de l’un des modèles, mettez-les comme ci-dessous.
\(pattern1\|pattern2\)
exemple: je souhaite rechercher tous les emplacements où une variable contenant le nom "date" est définie en tant que chaîne ou int. (par exemple, "int cronDate =" ou "String textFormattedDateStamp ="):
Avec
grep -E
, vous n'avez pas besoin d'échapper aux parenthèses ou au tuyau, c'est-à-diregrep -E '(int|String) [a-zA-Z_]*date[a-zA-Z_]* ='
la source
Ça marche pour moi
la source
Il y a plusieurs façons de le faire.
grep 'foo\|bar' *.txt
egrep 'foo|bar' *.txt
find . -maxdepth 1 -type f -name "*.txt" | xargs grep 'foo\|bar'
find . -maxdepth 1 -type f -name "*.txt" | xargs egrep 'foo|bar'
Les 3ème et 4ème options ne grèveront que dans les fichiers et éviteront que les répertoires aient
.txt
leurs noms.Ainsi, selon votre cas d'utilisation, vous pouvez utiliser l'une des options mentionnées ci-dessus.
Merci!!
la source
pour ajouter à la réponse de @ geekosaur , si vous avez plusieurs modèles qui contiennent également des onglets et de l'espace, utilisez la commande suivante
où
[[:blank:]]
est la classe de caractères RE qui représente un espace ou un caractère de tabulationla source