2013-06-13 15 views
6

Il mio esempio file della tabella assomiglia a quel file Nomeawk dichiarazioni - se non lo trova (grep'ed) fanno

Name1 xxxxx 34 
Name1 xxxxx 37 
Name2 aaaaa 59 
Name2 xxxxx 90 
Name4 Name3 12 

sembra che

Name1 
Name2 
Name3 
Name4 

voglio awk per abbinare Name1/2/3/4 da file Nome per caricare il file $ 1 e stampare la somma di $ 3. Se Nome non trovato stampa0 - come posso fare tale istruzione if in awk?

Quello che ho già fatto:

for i in $(cat Name_file) 
do 
cat table | awk -v NAME="$i" '($1==NAME) {SUM+=$3} END {print NAME"\t"SUM}' 
done 

restituisce un valore

Name1 71 
Name2 149 
Name3 
Name4 12 

E 'quasi perfetto - voglio aggiungere 0 per Name3 per ottenere

Name1 71 
Name2 149 
Name3 0 
Name4 12 

Tanto domanda tale uscita è: Come aggiungere la funzione if not found do in awk?

+2

mi può suggerire di usare 'invece di' $ (cat file) 'in' $ ( TrueY

+1

Intendi 'per i in $ (

+1

Sì, usa '$ ( TrueY

risposta

1

Prova sg come questo:

awk 'NR==FNR{a[$1]=0;next}$1 in a{a[$1]+=$3}END{for(i in a) print i,a[i]}' Name_file table 

uscita:

Name1 71 
Name2 149 
Name3 0 
Name4 12 

In questo caso non è necessario il anello intorno . Legge Names_table quindi elabora tutte le righe di table in un unico passaggio. Quindi è molto più efficace.

AGGIUNTO

O un soluzione pura (> = 4.0):

printf -v tmp "[%s]=0 " $(<Name_file) 
declare -A htmp 
eval htmp=($tmp) 
while read a b c; do [ -n "${htmp[$a]}" ] && ((htmp[$a] += $c)); done <table 
for i in ${!htmp[*]}; do echo $i ${htmp[$i]}; done 

ESTESA

La domanda esteso è stato quello di gruppo da $1 e $2 (e Name_file contiene tutte le prime chiavi da table, quindi non è reale ho bisogno di elaborare).

cat >table <<XXX 
Name1 xxxxx 34 
Name1 xxxxx 37 
Name2 aaaaa 59 
Name2 xxxxx 90 
Name4 Name3 12 
XXX 

awk -v SUBSEP=, '{a[$1,$2]+=$3;++n[$1,$2]}END{for(i in a) print i,a[i],n[i]}' table 

uscita:

Name2,xxxxx 90 1 
Name2,aaaaa 59 1 
Name4,Name3 12 1 
Name1,xxxxx 71 2 
+2

Il metodo stamperà le somme per tutte le linee, non solo nei nomi. Dovresti aggiungere la condizione '($ 1 in a)' per funzionare correttamente. Inoltre, stampa i conteggi in ordine casuale che potrebbero non essere desiderati. – Vovanium

+0

@Vovanium: Grazie! Aggiunto. In realtà non era nelle specifiche ... :) – TrueY

+0

Ho modificato la mia domanda originale 'table' come ho ancora una domanda. Mentre il codice scorre per ogni parola Name_file univoca e aggiunge $ 3 - è possibile distinguere ogni singola parola $ 2 per ogni parola unica $ 1 (gruppi di moduli come 'Nome1 xxxx',' Nome2 aaaa', 'Nome2 xxxx') e quindi somma $ 3 per ogni gruppo? Per ottenere tale risultato: 'Nome1 xxxx 71 2',' Nome2 aaaa 59 1', 'Nome2 xxxx 90 1'? $ 4 indica quante parole sono state unite per formare un gruppo. Se è troppo posso postare questa come una nuova domanda. –

2

Non è necessario alcun comportamento "non trovato". Non è stata appena inizializzata la variabile SUM prima del conteggio. Utilizzare BEGIN {SUM = 0} per quello.

Se è necessario che il comportamento trovato/non trovato sia esplicito, farlo in modo simile. Innanzitutto, inizializzare alcune variabili BEGIN {FOUND = 0}, quindi modificarlo in un modo corrispondente alla corrispondenza del modello: (...) {FOUND = FOUND+1} e infine testarlo con if(FOUND!=0).

+0

Cha! Così semplice :) Grazie. –

Problemi correlati