I have a small script called test.sh which prints the value based on the index given.
#!/bin/sh
days_in_month=(0 31 28 31 30 31 30 31 31 30 31 30 31)
echo "${days_in_month[$1]}"
The above code works fine if I execute using bash.
$ bash test.sh 1
31
But I need to execute the same script in an embedded board which has sh as part of Busybox package. When I run the command in that board, it throws an error.
$ sh test.sh
test.sh: line 2: syntax error: unexpected "("
I observe that the same error is thrown when I use dash instead of bash in Ubuntu system.
$ dash test.sh
test.sh: line 2: syntax error: unexpected "("
Is there any way that I could change the code so that Busybox sh will execute without any errors?
Both busybox' sh (which isash) and dash do not support arrays.
You could either write a big if-else or switch case statement, or use the following trick. We simulate an array using a single string with spaces as delimiters.
cut -d ' ' -f "$1" <<< "31 28 31 30 31 30 31 31 30 31 30 31"
or even more portable:
echo "31 28 31 30 31 30 31 31 30 31 30 31" | cut -d ' ' -f "$1"
Another workaround is to abuse the script's positional parameters as seen in this answer.
/bin/sh in general does not support arrays, apart from the list of positional parameters.
Let's use that:
#/bin/sh
pos=$1
if [ "$pos" -lt 1 ] || [ "$pos" -gt 12 ]; then
printf 'No such month: %s\n' "$pos" >&2
exit 1
fi
set -- 31 28 31 30 31 30 31 31 30 31 30 31
shift "$(( pos - 1 ))"
printf '%s\n' "$1"
This first picks out the number from the command line and puts it into pos. Then it sets the positional parameters that you had in your array. By shifting pos - 1 elements off this array, we have the wanted number in $1.
This would work even if the list contained strings with spaces in them, such as in
#/bin/sh
pos=$1
if [ "$pos" -lt 1 ] || [ "$pos" -gt 12 ]; then
printf 'No such month: %s\n' "$pos" >&2
exit 1
fi
set -- "thirty one" "twenty eight" "thirty one" etc.
shift "$(( pos - 1 ))"
printf '%s\n' "$1"
The other way to solve this with /bin/sh is with a case statement:
case $1 in
2)
echo 28 ;;
4|6|9|11)
echo 30 ;;
1|3|5|7|8|10|12)
echo 31 ;;
*)
print 'No such month: %s\n' "$1" >&2
exit 1
esac
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With