Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

I am a bit stuck. My task is to print the arguments to my script in reverse order except the third and fourth.

What I have is this code:

#!/bin/bash

i=$#
for arg in "$@"
do
    case $i
    in
        3) ;;
        4) ;;
        *) eval echo "$i. Parameter: \$$i";;
    esac
    i=`expr $i - 1`
done

As I hate eval (greetings to PHP), I am looking for a solution without it but I am not able to find one.

How can I define the position of the argument dynamically?

PS: No its not a homework, I am learning shell for an exam so I try to solve old exams.

share|improve this question
add comment

3 Answers 3

up vote 6 down vote accepted

eval is the only portable way. Your script would be clearer if you explicitly looped on the index rather than the values (which you aren't using). Note that you don't need expr unless you want your script to run in antique Bourne shells; $((…)) arithmetic is in POSIX. Limit the use of eval to the smallest possible fragment; for example, don't use eval echo, assign the value to a temporary variable.

i=$#
while [ $i -gt 0 ]; do
  if [ $i -ne 3 ] && [ $i -ne 2 ]; then
    eval value=\$$i
    echo "Parameter $i is $value"
  fi
  i=$((i-1))
done

In bash, you can use ${!i} to mean the value of the parameter whose name is $i. This works when $i is either a named parameter or a number (denoting a positional parameter). While you're at it, you can make use of other bash convenience features.

for ((i=$#; i>0; i--)); do
  if ((i != 3 && i != 4)); then
    echo "Parameter $i is ${!i}"
  fi
done
share|improve this answer
    
I can't use arg as they are ordered correctly and not in reverse. To the usage of expr, I am limited to use the standard only. –  WarrenFaith Sep 25 '11 at 16:07
1  
@WarrenFaith If your script starts with #!/bin/bash, you can use ${!i} and (()). If you want to stick to standard sh, these aren't available, but $((…)) is. –  Gilles Sep 25 '11 at 16:10
    
Ok, I think I can work with this :) –  WarrenFaith Sep 25 '11 at 16:11
add comment

I keep a script reverse on my path that does this:

#!/bin/sh

if [ $# -gt 0 ]; then
    arg=$1
    shift
    reverse $@
    echo $arg
fi

Example usage:

$ reverse a b c
c
b
a
share|improve this answer
add comment

This is a correct and non-dangerous use of eval. You fully control the content that you are evaling.

If it still gives you bad feelings, then if you don't care about portability, you can use Bash's ${!i} indirection syntax.

share|improve this answer
    
so ${!i} isn't part of the standard syntax? –  WarrenFaith Sep 25 '11 at 16:05
    
No, it's a Bashism. Here are the POSIX parameter expansions: pubs.opengroup.org/onlinepubs/009695399/utilities/… –  Shawn J. Goff Sep 25 '11 at 16:18
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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