Search code examples
bashlistwhile-loopmax

Bash - getting MAX value from a list of integers


This script breaks up the cvs list into three columns. we are focusing on the "name" column. I want to discover the name that has the most characters. Once I find the name with the most characters, I want to assign that to a variable.

#!/bin/bash
for i in $(cat homeaway.txt )
do
echo $i | while IFS=, read -r area name host
do
        maxLength=0
        length=${#name}
        if [ $length -gt $maxLength ] ; then
            maxLength=$length
        else
           :
        fi
        printf "%s\n" $maxLength

      done
done

The script says - in English - If the length is greater than maxlength, set length to maxLength, if not, do nothing. The area string with the most characters in it is "script_name_12345678999999" which has 26. When the script reads through all the characters, $maxLength should return 26.

__DATA__
HOME,script_name_12345,USAhost.com   
AWAY,script_name_123,USAhost.com
HOME,script_name_1,EUROhost.com
AWAY,script_name_123,USAhost.com
HOME,script_name_123456,EUROhost.com
AWAY,script_name_12345678999999,USAhost.com
HOME,script_name_1234,USAhost.com
AWAY,script_name_1234578,USAhost.com
HOME,script_name_12,EUROhost.com
AWAY,script_name_123456789,USAhost.com

Once the script reaches the area value with 26 characters in it, it should stop assigning anything to $maxLength. Instead it returns a list of each strings length, and I have no idea how the zero gets in here

casper@casper01.com $ ./length_test.sh
17
0   ### how does the zero get in here ?
15
13
15
18
26  ###script_name_12345678999999
16
19
14
21

Solution

  • Your loops are a bit wonky (technical term) and you are resetting maxLength to zero on every iteration of your loop. You want something a bit more like:

    #!/bin/bash
    
    fn="${1:-/dev/stdin}"   ## read from file given as 1st argument (default stdin)
    
    test -r "$fn" || {      ## validate file is readable 
        printf "error: file not readable '%s'.\n" "$fn"
        exit 1
    }
    
    declare -i maxlength=0  ## set maxlength before loop
    maxname=
    
    while IFS=, read -r area name host
    do
        test -n "$name" || continue            ## if name not set get next line
        len=${#name}
        if [ "$len" -gt "$maxlength" ]; then   ## test length against max
            maxlength=$len                     ## update max if greater
            maxname="$name"                    ## save name in maxname
        fi
    done <"$fn"                                ## feed loop by redirecting file
    
    printf "maxname: %s  (len: %d)\n" "$maxname" "$maxlength"
    

    Example Use/Output

    $ bash maxnm.sh <dat/maxnm.txt
    maxname: script_name_12345678999999  (len: 26)
    

    Look things over and let me know if you have further questions.