3

I want to output all arguments of a function one by one.
The function can receive many arguments, $# is the length of arguments.

showArg(){
    num=$#
    for order in `seq 1 ${num}`
    do
        echo $order
    done
}

To execute it.

showArg  x1 x2 x3 
1
2
3

How to fix the echo statement echo $order to get such the following output?

x1
x2
x3

I have tried echo $$order.

To call every argument with "$@" in for loop can list it, but it is not the way I expected.

showArg(){
    for var in "$@"
    do
        echo "$var"
    done
}
codeforester
  • 39,467
  • 16
  • 112
  • 140

3 Answers3

3

You can use indirection:

showArg() {
  num=$#
  for order in $(seq 1 ${num}); do # `$(...)` is better than backticks
    echo "${!order}"               # indirection
  done
}

Using a C-style loop (as suggested by @chepner & @CharlesDuffy), the above code can be rewritten as:

showArg() {
  for ((argnum = 1; argnum <= $#; argnum++)); do
    echo "${!argnum}"
  done
}

But Bash provides a much more convenient way to do it - use "$@":

showArgs() {
  for arg in "$@"; do  # can also be written as: for arg; do
    echo "$arg"        # or, better: printf '%s\n' "$arg"
  done
}

See also:

Charles Duffy
  • 280,126
  • 43
  • 390
  • 441
codeforester
  • 39,467
  • 16
  • 112
  • 140
  • 3
    Don't use `seq` at all; use a C-style `for` loop. – chepner May 26 '17 at 12:26
  • The first loop was just a correction to OP's original code. I kept the loop format because OP might have had an intention to put more logic inside, not just print. – codeforester May 26 '17 at 14:11
  • 1
    @codeforester, sure, but you don't need `seq` for that. `for ((order=1; order<=num; order++)); do ...` – Charles Duffy May 26 '17 at 16:23
  • 1
    Hmm. Might actually want to showcase `printf 'argument %d is %q\n' "$argnum" "${!argnum}"` or such -- that way you're printing the text in an `eval`-safe way that makes hidden characters (trailing DOS newlines or the like) visible. – Charles Duffy May 26 '17 at 16:34
2

You don't need an explicit loop:

printf '%s\n' "$@"
chepner
  • 497,756
  • 71
  • 530
  • 681
-4

Normally, it's easier to use "$*" to represent all arguments, so :

#!/bin/bash

for arg in $*
do
    echo $arg
done

In fact, this is the default behaviour for the 'for' loop, so the in can be left off :

#!/bin/bash

for arg
do
    echo $arg
done

If you really do want use sequence numbers, though, you can use the exclamation point syntax, which uses the value of the supplied variable as the name, so :

#!/bin/bash

num=$#
for order in $(seq 1 ${num})
do
    echo ${!order}
done
racraman
  • 4,988
  • 1
  • 16
  • 16
  • Using `$*` is *not* the default for `for`. – chepner May 26 '17 at 12:27
  • Try running any of your test scripts with the following argument list to observe some of the issues pointed out by prior commenters firsthand: `./yourscript "*" "hello world" $'goodbye\t\tworld'` – Charles Duffy May 26 '17 at 16:24