3

Having this code:

#!/bin/bash
for i in $#; do echo ${$i}; done

where $# should be number of vars from stdin, gives:

${$i}: bad substitution

How to list them without having to write echo $0; echo $1; echo ... And how to substitute variable itself in variable? (That is "building" var names by e.g. loop)

4

argv[] is not stdin.

The usual way is to avoid indexing entirely and iterate over the values directly (basically, how for..in is supposed to work in the first place). The special "array" variable representing all arguments is "$@" – yes, the quotes are necessary for array expansion to happen correctly:

for v in "$@"; do
    echo "Got $v"
done

(Don't do this with $* nor with unquoted $@ as both will mess up args containing spaces.)

However, if you do need indexes as well, the correct "dereference" syntax in bash is ${!i}:

for (( i = 1; i <= $#; i++ )); do
    echo "Item $i is ${!i}"
done

(Note the C-like syntax needed to iterate over a numeric range. While it's possible to do static ranges using for i in {1..10} that unfortunately doesn't work when variables like {1..$#} start getting involved. But you can use for i in $(seq 1 $#) if you don't mind the extra subprocess.)

Finally, one of the oldest methods is to repeatedly shift the list of arguments:

while [ "${1+yes}" ]; do
    echo "Got $1"
    shift
done

The ${var+string} expansion is used to check whether the variable is set to anything, instead of checking for non-zero-length strings. You might sometimes see this simplified to a more direct check – which is fine as long as you're 100% sure there won't be any zero-length args:

while [ "$1" ]; do
    echo "Got $1"
    shift
done
| improve this answer | |
3
#!/bin/bash

for i in "$@"; do echo "${i}"; done

Example:

$ ./s.sh a b c 'white space'
a
b
c
white space
| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.