Show duplicate GID in /etc/passwd with awk

Viewed 557

Hi I need to do this: Develop an AWK program that reads /etc/passwd and prints the names of those users having the same GID in the form GID name1 name2.

I was looking at this post on stackoverflow trying to develop a solution: awk + How do I find duplicates in a column?

The solution there kind of worked but was incomplete and was not formatted correctly.

I found this code on the Internet but can not get it to run:

awk -F: '{print $4}' /etc/passwd | sort | uniq -d > output.txt
awk -F: {kount[$4]++}
END{for {$1 in kount[$4]}}
printf("%d %s", $4, $1) output.txt

It is obvious it has some syntax problems with mixing the bash and awk code. I split it into two programs, a bash script and an awk script. The bash one works correctly it contains:

awk -F: '{print $4}' /etc/passwd | sort | uniq -d > output.txt

That program works correctly and gives me a file output.txt that contains the numbers 65534 and 7 which is correct.

I then tried writing the awk program to process that file and it looks like this:

BEGIN{ 
    FS=":" 
} 
    {a[$4]++} 

END{ 
    for {$1 in a[$4]}  
    {printf "%d %s", $4, $1}
}

and that doesn't work. I feel like I am really close but can't quite nail down the solution, any help would would much appreciated! Thanks in advance!

2 Answers

Could you please try following.

awk -F':' '{a[$4]=(a[$4]?a[$4] OFS:"")$1;b[$4]++} END{for(i in a){if(b[i]>1){print i,a[i]}}}' Input_file

This will give gid and then all users in a line which has same gid value, not tested.

Explanation: Adding explanation for above code.

awk -F':' '                           ##Starting awk program here and setting field separator as colon here.
{
  a[$4]=(a[$4]?a[$4] OFS:"")$1        ##Creating an array named a whose index is $4 and its value is $1 which will be keep concatenating itself on each occurrence.
}
END{
  for(i in a){                        ##Starting a for loop to traverse through all items of array a here.
    print i,a[i]                      ##Printing index is array a current element along with its value.
  }                                   ##Closing for loop BLOCK here.
}
' Input_file                          ##Mentioning Input_file name here.

If you are not tied to awk and can use a pure bash solution that requires no sub-shells:

#!/bin/bash

while IFS=: read name pw uid gid remain; do
  [ "${gid}" != "" ] && groups[${gid}]+="${name} "
done < /etc/passwd

for gid in ${!groups[@]}; do
  echo "${gid}: ${groups[${gid}]}"
done

Sample output:

0: root sync shutdown halt operator 
1: bin 
2: daemon 
4: adm 
7: lp 
...
Related