Handling Bash Parameters
Bash shell or shells in general hang on details. An ex-student was trying to sort something out in Learning the bash Shell, 3rd Edition, which isn’t on my short list of good shell scripting books. I concur more or less with the comment on Amazon.com that there are too few examples in the book. I think the free examples here may serve folks in lieu of a book.
Anyway, the student’s problem involved processing multiple word parameters in an array. They were confused about how to handle ${*}
, ${@}
"${*}"
and "${@}"
when assigning them into an array for subsequent processing. By the way, I did find a decent explanation of the concept on Page 89 in my copy of the book. Though my copy is a 2nd Edition.
Here’s a dressed up sample of what they were attempting to do:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 | #!/bin/bash # Print header information. echo "Begin Program!" echo "" # Count the call parameters. echo "Count call parameters [" ${#} "]" echo "" # Declare an array of delimited parameters. ARRAY=(${@}) # Declare a numeric constant of array elements. ELEMENTS=${#ARRAY[@]} # Does the parameter account agree with array elements. if [[ ${#} = ${#ARRAY[@]} ]]; then echo "Parameters match exploded array elements." else echo "Parameters ["${#}"] don't match exploded array elements ["${ELEMENTS}"]." fi # Echo line break. echo "" # Echo the parameter list. for (( i = 0; i < ${ELEMENTS}; i++ )); do echo " ARRAY["${i}"]=["${ARRAY[${i}]}"]" done # Print footer information. echo "" echo "End Program!" |
With the ARRAY=(${@})
assignment on line #12, they exploded the elements into individual words. They thought that the IFS
(Internal Field Separator) environment variable was defined wrong but it wasn’t.
They called the program like this from the command-line:
sample.sh "Me too" "You too" |
Then, they got this syntax and were surprised.
Begin Program! Count call parameters [ 2 ] Parameters [2] don't match exploded array elements [4]. ARRAY[0]=[Me] ARRAY[1]=[too] ARRAY[2]=[You] ARRAY[3]=[too] End Program! |
They were close. The ARRAY=(${@})
assignment on line #12. There attempt to fix it with ARRAY=(${*})
led nowhere because it’s more or less the same and explodes into 4 words. To their credit, they put quotes around it like this ARRAY=("${*}")
and got two parameters but one array element, as shown below:
Begin Program! Count call parameters [ 2 ] Parameters [2] don't match exploded array elements [1]. ARRAY[0]=[Me too You too] End Program! |
What they needed was ARRAY=("${@}")
on line #12 to explode quote delimited parameters. Here’s a complete working example of the final code.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 | #!/bin/bash # Print header information. echo "Begin Program!" echo "" # Count the call parameters. echo "Count call parameters [" ${#} "]" echo "" # Declare an array of delimited parameters. ARRAY=("${@}") # Declare a numeric constant of array elements. ELEMENTS=${#ARRAY[@]} # Does the parameter account agree with array elements. if [[ ${#} = ${#ARRAY[@]} ]]; then echo "Parameters match exploded array elements." else echo "Parameters ["${#}"] don't match exploded array elements ["${ELEMENTS}"]." fi # Echo line break. echo "" # Echo the parameter list. for (( i = 0; i < ${ELEMENTS}; i++ )); do echo " ARRAY["${i}"]=["${ARRAY[${i}]}"]" done # Print footer information. echo "" echo "End Program!" |
Changing that one element yields their desired output:
Begin Program! Count call parameters [ 2 ] Parameters match exploded array elements. ARRAY[0]=[Me too] ARRAY[1]=[You too] End Program! |
As always, I hope this helps some folks.