Existe-t-il un utilitaire de type grep qui me permettra de faire des recherches grep avec des opérateurs logiques. Je veux pouvoir imbriquer et combiner librement les constructions logiques. Par exemple, des trucs comme ça devraient être possibles:
grep (term1 && term2) || (term1 && (term3 xor term4)) *
Je sais que cela peut être fait avec Vanilla grep et des scripts bash supplémentaires, mais mon objectif ici est d'éviter d'avoir à le faire.
Avec awk
, comme avec Perl
, vous devrez encapsuler les termes dans //
, Mais cela peut être fait:
awk '(/term1/ && /term2/) || (/term1/ && xor(/term3/, /term4/))'
Il existe de nombreuses façons d'utiliser grep
avec des opérateurs logiques.
Utilisez \|
Pour séparer plusieurs modèles pour la condition OU .
Exemple: grep 'pattern1\|pattern2' filename
Utilisez l'option -E
Pour envoyer plusieurs modèles pour la condition OU .
Exemple: grep -E 'pattern1|pattern2' filename
L'utilisation d'un seul -e
Ne correspond qu'à un seul modèle, mais l'utilisation de plusieurs options -e
Correspond à plusieurs motifs.
Exemple: grep -e pattern1 -e pattern2 filename
grep -v
Peut simuler l'opération ET NON .
Il n'y a pas d'opérateur ET dans grep
, mais vous pouvez simuler par force brute ET en utilisant l'option -E
.
Exemple: grep -E 'pattern1.*pattern2|pattern2.*pattern1' filename
L'exemple ci-dessus correspondra à toutes les lignes contenant à la fois pattern1 et pattern2 dans l'un ou l'autre ordre.)
Vous pouvez utiliser Perl:
Perl -wne 'print if (/term1/ && /term2/) || (/term1/ && (/term3/ xor /term4/))'
Où les commutateurs sont les suivants:
-w turns on warnings
-n runs Perl against each line of input (looping)
-e executes Perl passed in the command line
J'utilise pour chaîner les commandes grep
pour obtenir un ET logique:
grep expr1 filename | grep expr2
Je pense que c'est assez simple, semblable à Unix et élégant.
Ensuite, vous pouvez combiner (comme @Tushi l'a expliqué en détail) avec le -E
option pour OR-ing et -v
pour la négation.
Votre exemple spécifique est assez méchant et bénéficierait probablement d'un utilitaire plus puissant (voir la réponse de @ muru).
sed '/term1/!d;/term2/b' -e '/term3/!d;/term4/d' *
Je crois que cela accomplit ce que vous essayez de faire. Il d
eletes de sortie toute ligne qui ne correspond pas term1
, il b
sort du script (et donc les impressions automatiques) toute ligne qui reste et qui correspond à term2
, et pour les lignes qui restent, il supprime celles qui ne correspondent pas term3
et parmi ceux qui correspondent à term4
.
sed
les scripts sont évalués dans l'ordre, et tous les tests sont booléens, donc toutes les actions résultant d'un test vont affecter directement le comportement des actions suivantes.