シェル引数を逆順に印刷

シェル引数を逆順に印刷

ちょっと立ち往生しています。私の使命は、3番目と4番目を除いて、スクリプトの引数を逆の順序で印刷することです。

私が持っているのは次のコードです。

#!/bin/bash

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

私はeval(PHPの帽子のヒント)が嫌いなので、それがないソリューションを探していますが、見つかりません。

パラメータの位置を動的に定義する方法は?

PS:いいえ、これは課題ではありません。私はテストのためにシェルを学んでいて、古いテストを解決しようとしています。

答え1

eval動的に選択された場所を介して位置パラメータにアクセスする唯一の移植可能な方法。 (使用しない)値の代わりにインデックスを明示的に繰り返すと、スクリプトはよりきれいになります。exprスクリプトをアンティークBourneシェルで実行したくない限り、操作$((…))はPOSIXにあります。使用をeval可能な限り最小の部分に制限します。たとえば、使用しないでeval echo一時変数に値を割り当てます。

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

Bashでは、を使用して名前付き${!i}パラメータの値を表すことができます$i。このメソッド$iは、名前付き引数または数値(位置引数を表す)の場合に機能します。使用すると、他のbashの便利な機能も活用できます。

for ((i=$#; i>0; i--)); do
  if ((i != 3 && i != 4)); then
    echo "Parameter $i is ${!i}"
  fi
done

答え2

reverse私は次のタスクを実行するスクリプトをパスに保持します。

#!/bin/sh

if [ "$#" -gt 0 ]; then
    arg=$1
    shift
    reverse "$@"
    printf '%s\n' "$arg"
fi

使用例:

$ reverse a b c '*' '-n'
-n
*
c
b
a

専用スクリプトの代わりに機能を使用することもできます。

答え3

位置パラメーターに改行文字が含まれていないとします。

[ "$#" -gt 0 ] && printf '%s\n' "$@" | #print in order
sed '3,4 d' |                          #skip 3 and 4
tac                                    #reverse (try tail -r on
                                       #non-GNU systems).

テスト:

set 1 2 3 4 5 6
printf '%s\n' "$@" | 
sed '3,4 d' |
tac

テスト出力:

6
5
2
1

答え4

そしてzsh

$ set a 'foo bar' c '' '*'
$ printf '<%s>\n' "${(Oa)@}"
<*>
<>
<c>
<foo bar>
<a>

Oa拡張時に配列要素をソートするために使用されるパラメータ拡張フラグ。キャンセル配列インデックス。

3と4を除く:

$ printf '<%s>\n' "${(Oa)@[5,-1]}" "${(Oa)@[1,2]}"
<*>
<foo bar>
<a>

関連情報