Imagine that we have two for example files. The first file is filled with unique names of employees created by combining the first two characters of the first name and the last 2 characters of the last name. Example : Peter Smith - Peht

First file contains :


The second file contains recordings about them when they logged into the system. ( Obviously there are also employees that are not listed in file1. )

The second file:

Mawo 21.4.2016 17:49
Peht 21.4.2016 17:58
Mawo 22.4.2016 7:58
Wato 22.4.2016 7:59
Stso 22.4.2016 8:02
Bavo 22.4.2016 8:15
Bane 22.4.2016 9:01
Bavo 23.4.2016 9:12
Mawo 23.4.2016 9:24
Dalo 23.4.2016 9:54
Peht 23.4.2016 9:58
Grma 24.4.2016 10:00

I need to find out how many times employes from file1 connected to the system ( file2 ).

What is the best way of doing that? The only solution which came to my mind is to make some 2 loops and for each name from file1 loop the whole file2 then grep names, ask if the names match if yes then count++. Could anyone give me some elegant solution for this problem using for example awk if it's possible?


Something simple like:

mapfile -t names < file1
for name in "${names[@]}"
  echo "${name}" $(grep -c "^$name " file2)

Will provide output like:

Peht 2
Mawo 3
Stso 1
Makr 0
Bavo 2

The grep string says to anchor the username at the beginning (^) of the line, and enforce a trailing space after the line.



FNR == NR{ 
($1 in names){
  for(name in ulog){
    print name ":" ulog[name]

and run it as awk -f test.awk user.list user.log

FNR==NR # does the file record number == the record number, if it does then we are still in the first file

next # as we are still in the first file, skip the rest and pull in the next line

The rest should be self explanatory

or as a one-liner

awk 'FNR == NR{ names[$1]; next } ($1 in names){ ulog[$1]++ } END{ for(name in ulog){ print name ":" ulog[name] } }' user.list user.log


Here's another way with join/sort/uniq:

join  -1 1 -2 2 -a1 -e "0" -o 1.1 2.1 <(sort file1) \
<(cut -d' ' -f1 file2 | sort | uniq -c)

Basically, it joins the names in file1 with the unique names and counts from file2 using 0 for the missing fields in file2.

With awk I would run:

awk 'NR==FNR{s[$1]++;next}
{if ($1 in s) {print $1, s[$1]}
else {print $1, 0}}' file2 file1

This reads file2 first, counts how many times each name occurs then reads file1 and for each name it prints the count from file2 (if a name is not in file2 it prints 0).

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.