0

I have a .csv file with entries like

Location,Indicator,Period,First Tooltip
Afghanistan,Malaria incidence (per 1 000 population at risk),2018,29
Afghanistan,Malaria incidence (per 1 000 population at risk),2017,27
Afghanistan,Malaria incidence (per 1 000 population at risk),2016,26
Afghanistan,Malaria incidence (per 1 000 population at risk),2015,15
Afghanistan,Malaria incidence (per 1 000 population at risk),2002,104
Afghanistan,Malaria incidence (per 1 000 population at risk),2001,92
Afghanistan,Malaria incidence (per 1 000 population at risk),2000,96
Algeria,Malaria incidence (per 1 000 population at risk),2018,0
Algeria,Malaria incidence (per 1 000 population at risk),2017,0
Algeria,Malaria incidence (per 1 000 population at risk),2013,0

I want to write a shell script that gives a country name as the argument to the shell
script returns and output like :

./scrip.sh Afghanistan  
For Afghanistan, the year is 2002; the rate is 104 per 1,000  

Basically, for that country, pick the line with max Tooltip and then parse it to produce
the above output.

My thoughts:
I am not sure how to do this using a shell script.
There are two parts here one is selecting the max, and then once we have that line
split it over, find out the numerical values and print it out.
Any hints or ideas on how to procees

4 Answers 4

3

Shell + awk:

#!/usr/bin/env sh

country="$1"

if [ -z "$country" ]
then
    printf "Country not specified\n" >&2
    exit 1
fi


awk -v FS=, -v country="$country" '
    BEGIN { tooltip = 0; found = 0 }
    $1 == country { if ($NF > tooltip) {found = 1; tooltip = $NF; year = $(NF - 1)} }
    END {if (!found) {print "No entry for the specified country"; exit 1} print "For " country " the year is " year "; the rate is " tooltip " per 1,000"}' file.csv

You didn't specify what's the name of the file so I used file.csv. Usage:

$ ./script.sh Afghanistan
For Afghanistan the year is 2002; the rate is 104 per 1,000
$ ./script.sh abc
No entry for the specified country
1
  • that was awesome. Please give some hints on how to do a similar thing, but now say the argument to the script is the year, and we want to find out the country which had the max entry for that year and display the exact details. May 4 at 11:06
1

Using sed

$ cat script.sh
#!/usr/bin/env bash

sed 's/ \+\([^,]*\),[^(]*(\([^0-9]*[0-9 ]*\)[^,]*,\([^,]*\),\(.*\)/For \1, the year is \3; the rate is \4 \2/' <(sed -n "/$1/p" input_file | sort -t',' -rnk4 | head -1)
$ ./script.sh Afghanistan
For Afghanistan, the year is 2002; the rate is 104 per 1 000
0

Suggesting solution with awk:

script.sh

#!/bin/bash
grep "$1" input.csv|sort -n -k 3 -t ","|tail -1|awk -F, '{gsub(" ","",$1);printf "For %s, the year is %d; the rate is %d per 1,000\n",$1,$3,$4}'
1
  • The column in sort is wrong. grep "$1" input.csv|sort -n -k 4 -t ","|tail -1|awk -F, '{gsub(" ","",$1);printf "For %s, the year is %d; the rate is %d per 1,000\n",$1,$3,$4}'
    – HatLess
    May 4 at 21:42
0

Here's a Perl script that will do what you ask. It's easy to extend if you need additional information later. It should work with the system Perl on any Unix/Linux box from the last 15 years or so.

#!/usr/bin/env perl

use 5.010;
use warnings;
use strict;

my $country = shift // die "Usage: $0 <country>\n";

my @rows = sort { $b->[3] <=> $a->[3] } 
           grep { $_->[0] eq $country } 
            map { chomp;[ split ',' ] } <>;

die "Country `$country' not found\n" if @rows == 0;

my $max = $rows[0];

say "For $country, the year is $max->[2]; the rate is $max->[3] per 1,000";

Sample output:

For Afghanistan, the year is 2002; the rate is 104 per 1,000

The script reads each line of STDIN with <>. The map, grep, and sort are done in order from bottom up: the map removes newlines (chomp) and splits the line on commas.

The grep then searches for rows where the country ($_->[0]; first column) is equal to $country.

Finally the sort sorts in reverse numerical order by the fourth column. ($_->[3]). So now we have all of the, say, Afghanistan rows, and the one with the highest value is at the top.

So now it's easy. We can just set $max to the first row ($rows[0]), and then it's just a matter of outputting your desired string.

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.