2009-10-29 7 views
1

Je passe la sortie d'un programme à travers quelques commandes awk, et je suis presque là où je dois être. La commande est à ce jour:Comment puis-je supprimer des lignes sélectionnées avec un script awk?

myprogram | awk '/chk/ { if ($12 > $13) printf("%s %d\n", $1, $12 - $13); else printf("%s %d\n", $1, $13 - $12) } ' | awk '!x[$0]++' 

Le dernier bit est un pauvre homme de uniq, ce qui est disponible sur mon objectif. Compte tenu de la chance la commande ci-dessus produit une sortie comme celle-ci:

GR_CB20-chk_2, 0 
GR_CB20-chk_2, 3 
GR_CB200-chk_2, 0 
GR_CB200-chk_2, 1 
GR_HB20-chk_2, 0 
GR_HB20-chk_2, 6 
GR_HB20-chk_2, 0 
GR_HB200-chk_2, 0 
GR_MID20-chk_2, 0 
GR_MID20-chk_2, 3 
GR_MID200-chk_2, 0 
GR_MID200-chk_2, 2 

Ce que je voudrais avoir est la suivante:

GR_CB20-chk_2, 3 
GR_CB200-chk_2, 1 
GR_HB20-chk_2, 6 
GR_HB200-chk_2, 0 
GR_MID20-chk_2, 3 
GR_MID200-chk_2, 2 

C'est, j'aimerais imprimer seule ligne qui a une valeur maximale pour une étiquette donnée (le premier 'champ'). L'exemple ci-dessus est représentatif des données at en ce que la sortie sera triée (comme si elle avait été passée par une commande sort).

+0

Si vous vous trouvez pressé pour l'espace et la vitesse, ce qui est pas l'optimisation prématurée, vous pouvez remplacer votre 'si ... printf ... else ... printf ...' la plus courte et, moins sur mon système, plus rapide "pauvre homme 'abs()' ": printf ("% s% d \ n ", 1 $, ((12 $> 13 $) * 2 - 1) * (12 $ - 13 $)' –

+0

, notez que votre commande 'awk' qui filtre les lignes sur'/chk/'peut être combinée dans mon script ci-dessous (avec des mods pour enregistrer les champs" prev "appropriés au lieu de la ligne entière, etc.) donc vous appelez seulement 'awk' une fois. En haut de mon script, 's' serait réglé sur' (($ 12> $ 13) * 2 - 1) * ($ 12 - $ 13) '* (non testé) * –

Répondre

2

Sur la base de mon answer à un besoin similaire, ce script maintient les choses en ordre et n'accumule pas un grand tableau. Il imprime la ligne avec la valeur la plus élevée de chaque groupe.

#!/usr/bin/awk -f 
{ 
    s = substr($0, 0, match($0, /,[^,]*$/)) 
    if (s != prevs) { 
     if (FNR > 1) print prevline 
     prevval = $2 
     prevline = $0 
    } 
    else if ($2 > prevval) { 
     prevval = $2 
     prevline = $0 
    } 
    prevs = s 
} 
END { 
    print prevline 
} 
+0

Beaucoup plus rapidement, et parce que la mémoire est une préoccupation (c'est un environnement intégré) je passe à cela comme la bonne réponse. – Jamie

1

Si vous ne avez pas besoin des articles à être dans le même ordre dans lequel ils ont été émis par myprogram, les travaux suivants:

... | awk '{ if ($2 > x[$1]) x[$1] = $2 } END { for (k in x) printf "%s %s", k, x[k] }' 
+0

Bien fait. Merci beaucoup. – Jamie

+0

Il manque juste le "\ n" dans printf(). Sinon parfait. – Jamie

+0

Ah, c'est vrai. Je l'ai eu dans ma version d'essai mais je l'oublie en le tapant ici. :) – jamessan