skip to Main Content

I’m trying to write a code where an organization is organizing an virtual event with a raffle and is identifying a subset of the attendees
that born in a certain month. Therefore, the event organizer needs to list only eligible members. The
members’ information is given in a CSV file, and the record format in this data file is as follow:

firstName,lastName,YYYYMMDD

However, the year can either be in a Gregorian calendar, where the current year is 2022, or a Buddhist calendar, where the current year is 2565.

2

Answers


  1. There are (at least) two reasons why the script doesn’t show anything with the example data.

    1. There is a bug in the date extraction d="${line##,}, as this just tries to remove a leading comma. The line should be:
    d="${line##*,}"
    
    1. There is a logic error when computing age: you always subtract the birth year from the current Gregorian year. This way, the only May-born person in your data file is 2023-2566 = -535 years old, which is not between 18 and 100. You need a way to tell which calendar is being used and compute the age accordingly.

    Finally, I’m not sure that echo "%sn" "$line" is going to give the intended output. You probably confused echo and printf.

    Login or Signup to reply.
  2. There are several issues with the code in the question, including syntax errors, logic errors, and some stylistic issues (e.g. use of magic numbers, unnecessary repetition). This Shellcheck-clean code attempts to fix most of them:

    #! /bin/bash -p
    
    month=$1
    csvfile=$2
    
    gregorian_year=$(date '+%Y')
    buddhist_year=$((gregorian_year + 542))
    
    months=( '' January February March April May June
                July August September October November December )
    
    while IFS=, read -r forename surname yyyymmdd ; do
        birth_year=${yyyymmdd:0:4}
        birth_month=${months[10#${yyyymmdd:4:2}]}
    
        age=$(( (birth_year > gregorian_year)
                ? (buddhist_year - birth_year)
                : (gregorian_year - birth_year) ))
    
        if [[ $birth_month == "$month" ]] && (( age > 18 && age < 100 )); then
            printf '%s,%s,%sn' "$forename" "$surname" "$yyyymmdd"
        fi
    done < "$csvfile"
    
    • The 10# in birth_month=${months[10#${yyyymmdd:4:2}]} forces the month number to be treated as a decimal (base 10) number. Otherwise 08 and 09 will cause errors as invalid octal numbers. See Value too great for base (error token is "08").
    • Note that the code does not produce any output given the arguments May guest.csv and the guest.csv contents given in the question because the only person born in May is only 7 years old.
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search