GNU/Linux >> Tutoriels Linux >  >> Ubuntu

Comment combiner une série d'instructions Grep regroupées en une seule instruction Grep ?

J'aimerais savoir s'il existe un moyen de combiner une série d'instructions grep où l'effet est de "et" les expressions plutôt que "ou" les expressions correspondantes.

Démo ci-dessous :

./script  
     From one grep statement, I want output like this
a b c

     not like this
a
c
a b
a b c
a b c d

Écoutez un aperçu du script.

 #!/bin/bash
 string="a
 b
 c
 d
 a b
 a b c
 a b c d"

 echo -e "\t From one grep statement I want output like this"
 echo "$string" |
 grep a |grep c |grep -v d #Correct output but pipes three grep statements

 echo -e "\n\tNot like this"
 echo "$string" |
 grep -e'a' -e'c' -e-v'd' #One grep statement but matching expressions are "or" versus "and"

Réponse acceptée :

Vous ne pouvez pas transformer le filtre grep a | grep c | grep -v d à un simple grep . Il n'y a que des moyens compliqués et inefficaces. Le résultat a des performances lentes et la signification de l'expression est obscurcie.

Combinaison de commande unique des trois greps

Si vous voulez juste exécuter une seule commande, vous pouvez utiliser awk qui fonctionne également avec des expressions régulières et peut les combiner avec des opérateurs logiques. Voici l'équivalent de votre filtre :

awk '/a/ && /c/ && $0 !~ /d/'

Je pense que dans la plupart des cas, il n'y a aucune raison de simplifier un tube en une seule commande, sauf lorsque la combinaison aboutit à une expression grep relativement simple qui pourrait être plus rapide (voir les résultats ci-dessous).

Les systèmes de type Unix sont conçus pour utiliser des tuyaux et pour connecter divers utilitaires ensemble. Bien que la communication par tuyau ne soit pas la plus efficace possible, elle est suffisante dans la plupart des cas. Parce qu'aujourd'hui, la plupart des nouveaux ordinateurs ont plusieurs cœurs de processeur, vous pouvez "naturellement" utiliser la parallélisation du processeur simplement en utilisant un tube !

Votre filtre d'origine fonctionne très bien et je pense que dans de nombreux cas le awk la solution serait un peu plus lente même sur un seul cœur.

Comparaison des performances

À l'aide d'un programme simple, j'ai généré un fichier de test aléatoire avec 200 000 000 lignes, chacune avec 4 caractères comme une combinaison aléatoire à partir des caractères a , b , c et d . Le fichier a 1 Go. Pendant les tests, il a été entièrement chargé dans le cache, de sorte qu'aucune opération de disque n'a affecté la mesure des performances. Les tests ont été exécutés sur Intel dual core.

Grep unique

$ time ( grep -E '^[^d]*a[^d]*c[^d]*$|^[^d]*c[^d]*a[^d]*$' testfile >/dev/null )
real    3m2.752s
user    3m2.411s
sys 0m0.252s

Awk unique

$ time ( awk '/a/ && /c/ && $0 !~ /d/' testfile >/dev/null )
real    0m54.088s
user    0m53.755s
sys 0m0.304s

Les trois greps d'origine sont canalisés

$ time ( grep a testfile | grep c | grep -v d >/dev/null )
real    0m28.794s
user    0m52.715s
sys 0m1.072s

Hybride – greps positifs combinés, canalisation négative

$ time ( grep -E 'a.*c|c.*a' testfile | grep -v d >/dev/null )
real    0m15.838s
user    0m24.998s
sys 0m0.676s

Ici, vous voyez que le seul grep est très lent à cause de l'expression complexe. Le tube original de trois greps est assez rapide grâce à une bonne parallélisation. Sans parallélisation - sur un seul cœur - le tube d'origine s'exécute juste un peu plus vite que awk qui, en tant que processus unique, n'est pas parallélisé. Awk et grep utilisent probablement le même code d'expressions régulières et la logique des deux solutions est similaire.

En relation :Combien d'années la version 11.10 est-elle prise en charge ?

Le gagnant clair est l'hybridation combinant deux greps positifs et laissant le négatif dans le tuyau. Il semble que l'expression régulière avec | n'a aucune pénalité de performance.


Ubuntu
  1. Comment fusionner plusieurs connexions Internet en une seule ?

  2. Comment descendre d'un répertoire ?

  3. Comment puis-je rechercher un motif multiligne dans un fichier ?

  4. Comment fusionner deux bibliothèques ar statiques en une seule?

  5. Comment puis-je exclure des répertoires de grep -R ?

Comment exclure dans la commande Grep sous Linux

Comment joindre plusieurs lignes en une seule dans un fichier sous Linux

Comment fusionner plusieurs fichiers PDF en un seul PDF sous Linux

Comment installer SpiderOak One sur Ubuntu 16.04 et Ubuntu 17.04

Comment diviser un fichier MP3 ?

Comment fusionner plusieurs comptes cPanel en un seul