J'essaie d'utiliser grep
pour afficher uniquement les lignes contenant l'un des deux mots, si un seul d'entre eux apparaît dans la ligne, mais pas s'ils sont sur la même ligne.
Jusqu'à présent, j'ai essayé, grep pattern1 | grep pattern2 | ...
mais je n'ai pas obtenu le résultat escompté.
[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?Réponses:
Un outil autre que
grep
le chemin à parcourir.En utilisant perl, par exemple, la commande serait:
perl -ne
exécute la commande donnée sur chaque ligne de stdin, qui dans ce cas imprime la ligne si elle correspond/pattern1/ xor /pattern2/
, ou en d'autres termes correspond à un modèle mais pas à l'autre (exclusif ou).Cela fonctionne pour le modèle dans l'un ou l'autre ordre, et devrait avoir de meilleures performances que les appels multiples de
grep
, et est également moins typé.Ou, encore plus court, avec awk:
ou pour les versions d'awk qui n'ont pas
xor
:la source
xor
disponible uniquement dans GNU Awk?/pattern1/+/pattern2/==1
irxor
manquant.\b
) dans les motifs eux-mêmes, c'est-à-dire\bword\b
.Avec GNU
grep
, vous pouvez passer les deux mots àgrep
, puis supprimer les lignes contenant les deux motifs.la source
Essayez avec
egrep
la source
grep -e foo -e bar | grep -v -e 'foo.*bar' -e 'bar.*foo'
Direct invocation as either egrep or fgrep is deprecated
- prefergrep -E
-f
et des-e
options bien que les plus anciennesegrep
etfgrep
continueront d'être prises en charge pendant un certain temps.grep
(qui supporte-F
,-E
,-e
,-f
comme POSIX exige) est/usr/xpg4/bin
. Les utilitaires dans/bin
sont obsolètes.Avec des
grep
implémentations qui prennent en charge les expressions régulières de type perl (commepcregrep
ou GNU ou ast-opengrep -P
), vous pouvez le faire en une seulegrep
invocation avec:C'est-à-dire trouver les lignes qui correspondent
pat1
mais paspat2
oupat2
paspat1
.(?=...)
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 avecpat1
etpat2
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:
(?(1)yespattern|nopattern)
correspond àyespattern
si le groupe de capture1
st (vide()
ci-dessus) correspond, etnopattern
sinon. Si cela()
correspond, cela signifiepat1
ne correspond pas, alors nous recherchonspat2
(regard positif devant), et nous ne cherchons paspat2
autrement (regard négatif devant).Avec
sed
, vous pourriez l'écrire:la source
grep: the -P option only supports a single pattern
, au moins sur tous les systèmes auxquels j'ai accès. +1 pour votre deuxième solution, cependant.grep
.pcregrep
et grep ast-open n'ont pas ce problème. J'ai remplacé le multiple-e
par l'opérateur RE d'alternance, donc cela devrait aussi fonctionner avec GNUgrep
.En termes booléens, vous recherchez A xor B, qui peut s'écrire
(A et non B)
ou
(B et non A)
Étant donné que votre question ne mentionne pas que vous vous souciez de l'ordre de sortie tant que les lignes correspondantes sont affichées, l'expansion booléenne de A xor B est assez simple en grep:
la source
sort | uniq
.Pour l'exemple suivant:
Cela peut être fait uniquement avec
grep -E
,uniq
etwc
.Si
grep
est compilé avec des expressions régulières Perl, vous pouvez faire correspondre la dernière occurrence au lieu de devoir diriger versuniq
:Sortez le résultat:
Un one-liner:
Si vous ne voulez pas coder en dur le modèle, son assemblage avec un ensemble variable d'éléments peut être automatisé avec une fonction.
Cela peut également être fait nativement dans Bash en tant que fonction sans canaux ni processus supplémentaires, mais serait plus impliqué et est probablement hors de portée de votre question.
la source
Big apple\n
etpear-shaped\n
, alors la sortie doit contenir ces deux lignes. Votre solution obtiendrait un nombre de 2; la version longue rapporterait «Les deux mots correspondent» (ce qui est une réponse à la mauvaise question) et la version courte ne dirait rien du tout. (3) Une suggestion: utiliser-o
ici est une très mauvaise idée, car elle masque les lignes qui contiennent les correspondances, donc vous ne pouvez pas voir quand les deux mots apparaissent sur la même ligne. … (Suite)uniq
/sort -u
et de l'expression régulière de Perl pour correspondre uniquement à la dernière occurrence de chaque ligne ne correspond pas vraiment à une réponse utile à cette question. Mais, même s'ils le faisaient, ce serait toujours une mauvaise réponse parce que vous n'expliquez pas comment ils contribuent à répondre à la question. (Voir la réponse de Stéphane Chazelas pour un exemple d'une bonne explication.)