Bash – (Bash) Editing contents of array from within function

bashshell-script

I'm trying to pad all the items of an array to 20 characters with whitespace, but can't seem to get my loop to work properly. It appears to increment through the array items correctly, but does not alter the items. Where am I going wrong here?

#!/bin/bash

testArray=( "bish" "bash" "bosh")

padLine () {
array=( "${@}" )
testLength=20
counter=0

##loop begins here##
for i in "${array[@]}";
do
size=${#array[$counter]}
testLength=20

#echo ""
#echo "size: " $size
#echo "Tlength: " $testLength
#echo "count: " ${array[$counter]}
#echo ""

if [ $size -lt $testLength ]
then 
    offset=$( expr $testLength - $size )

    #echo "Offset: " $offset

    case $offset in
        0)
            l0=""
            ;;
        1)
            l1=" "
            array[$counter]=${array[$counter]/%/$l1};;
        2)
            l2="  "
            array[$counter]="${array[$counter]/%/$l2}";;
        3)
            l3="   "
            array[$counter]=${array[$counter]/%/$l3};;
        4)
            l4="    "
            array[$counter]="${array[$counter]/%/$l4}";;
        5)
            l5="     "
            array[$counter]="${array[$counter]/%/$l5}";;
        6)
            l6="      "
            array[$counter]=${array[$counter]/%/$l6};;
        7)
            l7="       "
            array[$counter]=${array[$counter]/%/$l7};;
        8)
            l8="        "
            array[$counter]=${array[$counter]/%/$l8};;
        9)
            l9="         "
            array[$counter]=${array[$counter]/%/$l9};;
        10)
            l10="          "
            array[$counter]=${array[$counter]/%/$l10};;
        11)
            l11="           "
            array[$counter]=${array[$counter]/%/$l11};;
        12)
            l12="            "
            array[$counter]=${array[$counter]/%/$l12};;
        13)
            l13="             "
            array[$counter]=${array[$counter]/%/$l13};;
        14)
            l14="              "
            array[$counter]=${array[$counter]/%/$l14};;
        15)
            l15="               "
            array[$counter]=${array[$counter]/%/$l15};;
        16)
            l16="                "
            array[$counter]=${array[$counter]/%/$l16};;
        17)
            l17="                 "
            array[$counter]=${array[$counter]/%/$l17};;
        18)
            l18="                  "
            array[$counter]=${array[$counter]/%/$l18};;
        19)
            l19="                   "
            array[$counter]=${array[$counter]/%/$l19};;

        *)
    esac
fi
counter=$( expr $counter + 1 )  
done
}

padLine "${testArray[@]}"


echo -e "${testArray[0]}" 
echo -e "${testArray[1]}"
echo -e "${testArray[2]}"

Expected output:

bish                #lines end here, padded to 20 chars
bash                #                
bosh                #

Actual output:

bish# no padding
bash
bosh

Best Answer

Just for output:

array=( bish bash bosh )
printf '%-20s#\n' "${array[@]}"

This would produce

bish                #
bash                #
bosh                #

... where # occurs in column 21.

To make a new array (and printing it):

array=( bish bash bosh )

for elem in "${array[@]}"; do
    padarr+=( "$( printf '%-20s#' "$elem" )" )
done

printf '%s\n' "${padarr[@]}"

With /bin/sh, just printing:

set -- bish bash bosh
printf '%-20s#\n' "$@"

With /bin/sh, modifying $@ in-place:

set -- bish bash bosh
i=0
while [ "$i" -lt "$#" ]; do
    set -- "$@" "$( printf '%-20s#' "$1" )"
    shift
    i=$(( i + 1 ))
done

printf '%s\n' "$@"

The printf formatting string %-20s reserves 20 characters for a left-justified string.


As a bash (4.3+) function:

pad_array () {
    local padlen=$1
    local -n localarray=$2

    local -a tmp
    local elem

    for elem in "${localarray[@]}"; do
        tmp+=( "$( printf '%-*s#' "$padlen" "$elem" )" )
    done

    localarray=( "${tmp[@]}" )
}

myarray=( bish bash bosh )
pad_array 20 myarray

printf '%s\n' "${myarray[@]}"

The pad_array function here additionally allows you to choose the amount of padding.

The array is passed by its name and is received by the function in a name reference variable. This means that whenever the name reference is accessed in the function, the named variable are actually used.

Related Question