web-dev-qa-db-ja.com

$ @第一引数を除く

このように実行するシェルスクリプトを記述する必要があります。

./myscript arg1 arg2_1 arg2_2 arg2_3 ....... arg2_#

スクリプト内にforループがあります

for i in $@

ただし、知っているように、$ @には$ 1から$($#-1)までが含まれます。しかし、私のプログラムでは$ 1は$ 2 $ 3 $ 4などとは明らかに異なります。$ 2から最後までループしたいのですが、どうすればこれを実現できますか?ありがとうございました:)

46
user40780

まず、引用符なしの$@は意味がないため、使用しないでください。 $@は引用符付き("$@")およびリストコンテキストでのみ使用する必要があります。

for i in "$@"はリストコンテキストと見なされますが、ここでは、位置パラメーターをループ処理するために、標準的で最も移植性が高く、より単純な形式を示します。

for i
do something with "$i"
done

次に、2番目の要素からループするために、shiftを使用するのが標準的で最も移植性の高い方法です。

first_arg=$1
shift # short for shift 1
for i
do something with "$i"
done

shiftの後、以前は$1であったものがリストから削除され(ただし、$first_argに保存しました)、$2で使用されていたものが$1に追加されました。位置パラメータはshifted1の位置が左にあります(shift 2を使用して2だけシフトします...)。つまり、基本的に、ループは2番目の引数であったものから最後の引数までループします。

bash(およびzshksh93ですが、それだけです)では、代わりに次のようにします。

for i in "${@:2}"
do something with "$i"
done

ただし、これは標準のsh構文ではないため、#! /bin/sh -で始まるスクリプトでは使用しないでください。

zshまたはyashでは、次のこともできます。

for i in "${@[3,-3]}"
do something with "$i"
done

3番目から最後の3番目の引数にループします。

zshでは、$@$argv配列とも呼ばれます。したがって、配列の最初または最後から要素をポップするには、次のようにすることもできます。

argv[1,3]=() # remove the first 3 elements
argv[-3,-1]=()

shiftzsh1=()と書くこともできます)

bashでは、set組み込みの$@要素にのみ割り当てることができるため、最後から3つの要素をポップするには、次のようになります。

set -- "${@:1:$#-3}"

そして、3番目から最後の3番目にループするには:

for i in "${@:3:$#-5}"
do something with "$i"
done

POSIXly、"$@"の最後の3つの要素をポップするには、ループを使用する必要があります。

n=$(($# - 3))
for arg do
  [ "$n" -gt 0 ] && set -- "$@" "$arg"
  shift
  n=$((n - 1))
done
55

shift組み込みが必要だと思います。 $2$1$3$2など.

このような:

shift
for i in "$@"; do
    echo $i
done
10
John

穴居人のアプローチは常にあります:

first=1
for i
do
        if [ "$first" ]
        then
                first=
                continue
        fi
        something with "$i"
done

これは$@そのまま(後で使用したい場合)、すべての引数をループしますが、最初の引数は処理しません。

2
Scott

Bashでは、明示的なインデックス付けでそのループを記述することもできます。

_for ((i=2; i<=$#; ++i)); do
  process "${!i}"
done
_

これにより、2番目の引数から最後の引数までのすべての引数が繰り返されます。代わりに最後の引数を除外したい場合は、これを単純にしてください

_for ((i=1; i<=$#-1; ++i)); do
  process "${!i}"
done
_

そして、あなたが他のすべての議論をとりたいだけなら、それを次のように書いてください

_for ((i=1; i<=$#; i+=2)); do
  process "${!i}"
done
_

この背後にある物語は、 _($ /// =)for builtinarithmetic バージョンと、 argument-count _$#_ および 変数間接指定_${…}_

素敵なアプリケーションの1つは、これを使用して、ループ内で、指定されたオプションがそれに続く引数を値として取るかどうかを決定できることです。ある場合は、iをインクリメントして(たとえば、: $((++i))を書き込んで)、次の値を消費し、反復中にスキップします。

1
MvG