2013-06-13 16 views
6

Mój przykład plik tabela wygląda takawk oświadczenia - jeśli nie znaleziono (grep'ed) zrobić

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

nazwa pliku wygląda tak

Name1 
Name2 
Name3 
Name4 

Chcę awk dopasować Name1/2/3/4 z pliku Nazwa złożyć plik $ 1 i wydrukować sumę 3 $. Jeśli Nazwa nie zostanie znaleziona, wydrukuj0 - jak mogę zrobić takie oświadczenie if w awk?

Co ja już zrobione:

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

daje argumenty wyjściowe

Name1 71 
Name2 149 
Name3 
Name4 12 

To prawie idealny - Chcę dodać 0 do Name3 dostać takiego pliku

Name1 71 
Name2 149 
Name3 0 
Name4 12 

Tyle pytanie to: Jak dodać funkcję awk?

+2

mogę zasugerować użycie '$ ( TrueY

+1

Masz na myśli 'dla i in $ (

+1

Tak, użyj '$ ( TrueY

Odpowiedz

1

sg Spróbuj tak:

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 

wyjściowa:

Name1 71 
Name2 149 
Name3 0 
Name4 12 

W tym przypadku nie trzeba pętlę wokół . Odczytuje najpierw Names_table, a następnie przetwarza wszystkie linie table w jednym kroku. Jest o wiele bardziej efektywny.

DODATKOWA

lub czysty (> = 4,0) roztworu:

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 

EXTENDED

rozszerzony pytanie do grupy, $1 i $2 (i Name_file zawiera wszystkie pierwsze klucze od table, więc nie jest prawdziwe potrzebne do przetworzenia).

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 

wyjściowa:

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

Twoja metoda wypisze sumy dla wszystkich linii, nie tylko wymienionych w nazwach. Powinieneś dodać warunek '($ 1 in a)', aby działał poprawnie. Ponadto wydrukowałby liczby w losowej kolejności, co może być niepożądane. – Vovanium

+0

@Vovanium: Dzięki! Dodany. Właściwie to nie było w specyfikacji ... :) – TrueY

+0

Edytowałem moje oryginalne pytanie 'table', ponieważ mam jeszcze jedno pytanie. Gdy twój kod zamienia się na każde unikalne słowo Name_file i dodaje 3 $ - czy możliwe jest rozróżnienie każdego unikalnego słowa o wartości 2 $ za każde unikalne słowo o wartości 1 $ (grupy formularzy, takie jak "Name1 xxxx", "Name2 aaaa", "Name2 xxxx"), a następnie suma 3 $ za każdą grupę? Aby uzyskać taki wynik: 'Name1 xxxx 71 2',' Name2 aaaa 59 1', 'Name2 xxxx 90 1'? 4 USD określa liczbę słów połączonych w grupę. Jeśli jest za dużo, mogę napisać to jako nowe pytanie. –

2

Nie trzeba żadnego zachowania "nie znaleziono". Po prostu nie została poprawnie zainicjowana zmienna SUM przed zliczaniem. Użyj do tego celu BEGIN {SUM = 0}.

Jeśli potrzebujesz znaleźć/nie znaleziono zachowanie jawnie, zrób to podobnie. Najpierw zainicjuj zmienną BEGIN {FOUND = 0}, a następnie zmień ją w pewien sposób na dopasowaniu do wzorca: (...) {FOUND = FOUND+1} i na koniec przetestuj ją za pomocą if(FOUND!=0).

+0

Cha! Tak prosty :) Dzięki. –

Powiązane problemy