J'essaie de construire une recherche grep qui recherche un terme mais exclut les lignes qui ont un second terme. Je voulais utiliser plusieurs options -e "pattern"
mais cela n'a pas fonctionné.
Voici un exemple de commande que j'ai essayée et le message d'erreur généré.
grep -i -E "search term" -ev "exclude term"
grep: exclude term: No such file or directory
Il me semble que le -v
s'applique à tous les termes/modèles de recherche. Comme cela fonctionne mais n'inclut pas search term
dans les résultats.
grep -i -E "search term" -ve "exclude term"
Pour et expressions avec grep, vous avez besoin de deux invocations:
grep -Ei "search term" | grep -Eiv "exclude term"
Si les termes que vous recherchez ne sont pas des expressions régulières, utilisez une correspondance de chaîne fixe (-F
) qui est plus rapide:
grep -F "search term" | grep -Fv "exclude term"
À moins d’appeler grep à deux reprises, il n’ya qu’une façon d’y parvenir. Cela implique des expressions régulières compatibles avec Perl (PCRE) et des assertions plutôt approximatives .
Pour rechercher foo à l'exception des correspondances contenant bar , vous pouvez utiliser:
grep -P '(?=^((?!bar).)*$)foo'
Voici comment ça fonctionne:
(?!bar)
correspond à tout ce qui n'est pas bar sans utiliser les caractères de la chaîne. Alors .
consomme un seul caractère.
^((?!bar).)*
répète ce qui précède depuis le début de la chaîne (^
) jusqu'à la fin de celle-ci ($
). Il échouera si bar
est rencontré à un moment donné, puisque (?!bar)
ne correspondra pas.
(?=^((?!bar).)*$)
s'assure que la chaîne correspond au modèle précédent, sans utiliser les caractères de la chaîne.
foo
cherche foo comme d'habitude.
J'ai trouvé ce hack dans Une expression régulière pour faire correspondre une chaîne ne contenant pas un mot? . Dans la réponse de de Bart Kiers , vous pouvez trouver une explication beaucoup plus détaillée du fonctionnement de la prévision négative.
Format:
echo "some text" | awk '/pattern to match/ && !/pattern to exclude/'
Exemples:
echo "hello there" | awk '/hello/ && !/there/'
Ne renvoie rien.
echo "hello thre" | awk '/hello/ && !/there/'
Retours: bonjour thre
echo "hllo there" | awk '/hello/ && !/there/'
Ne renvoie rien.
Exemples:
echo "hello thre" | awk '(/hello/ || /hi/) && !/there/'
Retours: bonjour thre
echo "hi thre" | awk '(/hello/ || /hi/) && !/there/'
Retours: salut trois
echo "hello there" | awk '(/hello/ || /hi/) && !/there/'
Ne renvoie rien.
echo "hi there" | awk '(/hello/ || /hi/) && !/there/'
Ne renvoie rien.
D'après mes expériences, il ne semble pas que cela fasse beaucoup de différence si vous dirigez vos termes exclus par grep
ou sed
. Sed possède d'autres fonctionnalités utiles de remplacement de texte que j'utilise souvent pour mieux filtrer la sortie des fichiers journaux. Je vais donc utiliser sed car je combine pas mal de filtres sur sed.
wc /var/log/Tomcat/tomcat.2013-01-14.log.1 1851725 /usr/bin/time grep -i - E "(loginmanager)" /var/log/Tomcat/tomcat.2013-01-14.log.1 | sed -e "/ login OK/d" -e "/ Connexion expirée/d" | wc 24.05utilisateur 0.15système 0: 25.27effondré à 95% de l'UC (0avgtext + 0avgdata 3504maxresident) k 0sortie + 0 sorties (0major + 246minor) pagefaults 0swaps . .] /usr/bin/time grep -i -E "(loginmanager)" /var/log/Tomcat/tomcat.2013-01-14.log.1 | sed -e "/ login OK/d" -e "/ Connexion expirée/d" | wc 23.50user 0.16système 0: 24.48effondré à 96% de l'UC (0avgtext + 0avgdata 3504maxresident) k 0puts + 0outputs (0major + 246minor) pagefaults 0swaps . .] /usr/bin/time grep -i -E "(loginmanager)" /var/log/Tomcat/tomcat.2013-01-14.log.1 | grep -v -e "login OK" -e "Login expiré" | wc 23.08user 0.14system 0: 23.55effondrer à 98% du CPU (0avgtext + 0avgdata 3504maxresident) k 0puts + 0outputs (0major + 246minor) pagefaults 0swaps . .] /usr/bin/time grep -i -E "(loginmanager)" /var/log/Tomcat/tomcat.2013-01-14.log.1 | grep -v -e "login OK" -e "Login expiré" | wc 23.50user 0.15système 0: 25.27a échoué à 93% de l'UC (0avgtext + 0avgdata 3488maxresident) k 0puts + 0putputs (0major + 245minor) pagefaults 0swaps . .]