ちょっと立ち往生しています。私の使命は、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>