How do i print arguments in reverse order in shell

2019-03-06 05:38发布

问题:

This question already has an answer here:

  • Print bash arguments in reverse order 4 answers

I was trying to write a script that print the arguments in reverse order. So if I type bash reverse.sh one two three I expect my output to be three two one How can i do this? This is what I tried and it obviously didn't work...

#!/bin/bash
i=0
a="$"
for word in $*; do
  echo $a$(($#-i))
  i=$((i+1))
done  

This is the output i get

$3
$2
$1

I thought this would print the parameters in order 3, 2, 1 but it didn't. How should I do it? Any help will be much appreciated. Thank you.

回答1:

You need eval with echo i.e. you need to evaluate the expansion, not output it:

eval echo $a$(($#-i))

Note that, using eval in general is discouraged as this could result in security implications if the input string is not sanitized. Check John1024's answer to see how this can be done without eval.



回答2:

Let's define your arguments:

$ set -- one two three

Now, let's print them out in reverse order:

$ for ((i=$#;i>=1;i--)); do echo "${!i}"; done
three
two
one

How it works

for ((i=$#;i>=1;i--)) starts a loop in which i counts down from $# to 1. For each value of i, we print the corresponding positional parameter by ${!i}. The construct ${!i} uses indirection: instead of returning the value of i, ${!i} returns the value of the variable whose name is $i.

As a script

In a multi-line script form, we can use:

$ cat reverse 
#!/bin/bash
for ((i=$#;i>=1;i--))
do
   echo "${!i}"
done

As an example:

$ bash reverse One Two Three
Three
Two
One

Alternative: using tac

Another way to print things in reverse order is to use the utility tac. Consider this script:

$ cat reverse2
#!/bin/bash
printf "%s\n" "$@" | tac

Here is an example:

$ bash reverse2 Uno Dos Tres
Tres
Dos
Uno

printf "%s\n" "$@" prints out the positional parameters one per line. tac prints those lines in reverse order.

Limitation: The tac method only works correctly if the arguments do not themselves contain newlines.