share
Unix & LinuxDisplaying content of highest value in shell scripting
[-1] [5] Nosi Chefane Jnr
[2020-04-18 11:39:04]
[ shell scripting ]
[ https://unix.stackexchange.com/questions/580892/displaying-content-of-highest-value-in-shell-scripting ]

Record.txt has the following information

Nosi IT 3000
David HR 4000

How can display name an salary of highest paid employee using awk or any other tool that may work. if they are stored in records.txt. I want it to display David 4000

[+1] [2020-04-18 23:03:46] Shawn

Using the always-handy GNU datamash [1]:

$ datamash -Wf max 6 < record.txt | cut -f 4,6
David   4000

Use datamash to print out the line with the highest value in the 6th column, and cut to get just the columns you care about.

[1] https://www.gnu.org/software/datamash/

1
[+1] [2020-04-20 11:38:27] Alex Stragies

[1] version:

awk 'NF && $3>max {max=$3; id=$1} END {print id" "max}' records.txt

This reads as: "In lines with fields (=not empty), if the salary is higher than the current stored maximum (default 0), then update the stored maximum value and the name of the champion. When all lines are processed (= END), dump out both variables containing ID and salary.

For reasons of speed I would probably choose this approach with [2] though:

sort -k 3 -n -r records.txt | head -n 1
[1] /questions/tagged/awk
[2] /questions/tagged/sort

2
[+1] [2020-04-20 11:39:39] AdminBee

If you want to use awk, the following should work for the sample input you provided:

awk 'NF==0 {next} !name {max=$3; name=$1} {if ($3>max) {max=$3; name=$1};} END{printf("%s : %d\n",name,max)}' records.txt

It will skip empty lines and initialize the maximum value max and the corresponding name with the data from the first non-empty line (indicated by the name variable being 0, i.e. uninitialized if one expects a string here). It will replace them with the corresponding values of later (non-empty) lines if the salary encountered is greater then the current max. In the end, it prints name and value.

An even shorter version, as suggested by Stephen Kitt and Alex Stragies:

awk 'NF>0 && (!name || $3>max) {max=$3; name=$1} END {printf("%s : %d\n",name,max);}' records.txt

This makes use of the fact that setting max and name is the same for the first non-empty line and every line with column 3 value greater then max, and so the same action block can be used by checking if either of the two cases applies. And skipping empty lines can simply be incorporated, too, by demanding NF>0 as a precondition to do anything in the first place.


@StephenKitt Yes, that does make it more compact! I will include it in the answer. - AdminBee
@StephenKitt As to why I didn't completely include it: although it fully works in the current example where all numbers are positive, in the more general case of "finding the highest value in column 3" where numbers can be negative and the highest value actually 0, it may miss that highest value if empty lines are present. This is rather far-fetched, I agree, but I tried to make it as generally applicable as I could imagine. - AdminBee
(1) Indeed, if the maximum can be negative or nil, the short version doesn’t work and there has to be a distinction between “0” and “no value”. - Stephen Kitt
(1) the call to next can be golfed here in this specific case, just NF&&(!name||$3>max){....}. I used that in my answer as an alternative to the sort | head solution. - Alex Stragies
3
[0] [2020-04-18 12:27:13] binarysta

The idea is to convert it to 3-column format and then sort based on salary column.

$ cat file
Nosi IT 3000 David HR 4000 John Security 3500 George Finance 3700

$ awk -v RS='[ \n]' '{a=$0;getline b; getline c; print a,c}'  file | sort -rnk2 | head -1
David 4000

This outputs David as he's first in alphabet, not highest paid. - RudiC
4
[0] [2020-04-27 13:59:12] Kusalananda
$ sort -k3,3rn file | head -n 1
David HR 4000

This sorts the file numerically on the 3rd column in decreasing order, then picks out first line of that result using head.

If the file has tabs as field delimiters, use -t $'\t' with sort. That way, you would also be able to have fields with spaces in them.

To only display the name and the salary, use awk '{ print $1,$3; exit }' instead of head -n 1.


5