Carlos González Carlos González - 6 months ago 11
Bash Question

Bash while if function

I'm try to run this bash script.

#!/bin/sh

MAX=5

j=1

while [ $((1+$j)) -le $MAX ] do

input=$j

if [ $input -le $j ] then
echo "input=$j,$j,$((j+1)),$((j+2)),$((j+3)),$((j+4))"
else
echo "$input"
fi j=$((j+1))

done


I am writing a bash script and trying to check the order list provided in the argument of the shell values. The ouput has the content as:

input=1,1,2,3,4,5
input=2,2,3,4,5,6
input=3,3,4,5,6,7
input=4,4,5,6,7,8


As what I expect it should give the list in increase order at the each line but the result that i'm looking for is:

input=1,2,3,4,5
input=2,1,3,4,5
input=3,1,2,4,5
input=4,1,2,3,5
input=5,1,2,3,4


Please help me, thanks.

Answer

In your script, when you are iterating on variable j, only the while loop is keeping track of the range {1 .. MAX}. Hence, if you are at j=5 in your loop, then running echo on $j,$((j+1)),$((j+2)),$((j+3)),$((j+4)) results 5,6,7,8,9 respectively, which is not what you are looking for.

One approach at a solution is, given a number i, creating a range {1 .. MAX} with i removed. For example, given i=2, creating the list 1,3,4,...,MAX. This can then be concatenated to the final output format as echo "input=$i,$list".

The following range routine creates such a list:

# range() outputs a range of numbers 1 to MAX, but with
#    the number 'num' removed from the range.
# Usage: range num MAX
# Example: [ input: range 2 5 ] [ output: 1,3,4,5 ]
range() {
    num="$1"
    MAX="$2"
    for i in $(eval echo {1..$MAX}); do
        if [ "$num" -eq "$MAX" ]; then
            if [ "$i" -eq $((MAX-1)) ]; then
                printf "$i"
                break
            else
                printf "$i,"
            fi
        elif [ "$i" -eq "$MAX" ]; then
            printf "$i"
        elif [ "$i" -eq "$num" ]; then
            continue
        else
            printf "$i,"
        fi
    done
    printf "\n"
}

Then your while loop becomes,

j=1
MAX=5

while [ "$j" -le "$MAX" ]; do
    list=$(range "$j" "$MAX")
    echo "input=$j,$list"
    j=$((j+1))
done

whereby list variable is assigned the values of the range created with range "$j" "$MAX", then list is concatenated to final output.


Tests: Assuming the above script is named permute,

# when j=1 and MAX=5
$ ./permute
input=1,2,3,4,5
input=2,1,3,4,5
input=3,1,2,4,5
input=4,1,2,3,5
input=5,1,2,3,4

# when j=1 and MAX=10
$ ./permute
input=1,2,3,4,5,6,7,8,9,10
input=2,1,3,4,5,6,7,8,9,10
input=3,1,2,4,5,6,7,8,9,10
input=4,1,2,3,5,6,7,8,9,10
input=5,1,2,3,4,6,7,8,9,10
input=6,1,2,3,4,5,7,8,9,10
input=7,1,2,3,4,5,6,8,9,10
input=8,1,2,3,4,5,6,7,9,10
input=9,1,2,3,4,5,6,7,8,10
input=10,1,2,3,4,5,6,7,8,9