Avec des grep
implémentations qui prennent en charge les expressions régulières de type perl (comme pcregrep
ou GNU ou ast-opengrep -P
), vous pouvez le faire en une seule grep
invocation avec:
grep -P '^(?=.*pat1)(?!.*pat2)|^(?=.*pat2)(?!.*pat1)'
C'est-à-dire trouver les lignes qui correspondent pat1
mais paspat2
ou pat2
pas pat1
.
(?=...)
et (?!...)
sont respectivement des opérateurs d'anticipation et d'anticipation négative. Donc, techniquement, ce qui précède cherche le début du sujet ( ^
) à condition qu'il soit suivi par.*pat1
et non suivi .*pat2
, ou le même avec pat1
et pat2
inversé.
Ce n'est pas optimal pour les lignes qui contiennent les deux modèles car ils seraient ensuite recherchés deux fois. Vous pouvez utiliser à la place des opérateurs Perl plus avancés comme:
grep -P '^(?=.*pat1|())(?(1)(?=.*pat2)|(?!.*pat2))'
(?(1)yespattern|nopattern)
correspond à yespattern
si le groupe de capture 1
st (vide ()
ci-dessus) correspond, et nopattern
sinon. Si cela ()
correspond, cela signifie pat1
ne correspond pas, alors nous recherchonspat2
(regard positif devant), et nous ne cherchons pas pat2
autrement (regard négatif devant).
Avec sed
, vous pourriez l'écrire:
sed -ne '/pat1/{/pat2/!p;d;}' -e '/pat2/p'
[a-z][a-z0-9]\(,7\}\(\.[a-z0-9]\{,3\}\)+
? (2) Que se passe-t-il si l'un des mots / motifs apparaît plus d'une fois sur une ligne (et que l'autre n'apparaît pas)? Est-ce l'équivalent du mot apparaissant une fois, ou cela compte-t-il comme plusieurs occurrences?