1番目の引数を除く$ @


36

この方法で実行されるシェルスクリプトを作成する必要があります。

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

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

for i in $@

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

回答:


47

まず、$@引用符がないと意味がなく、使用しないでください。$@引用符("$@")およびリストコンテキストでのみ使用してください。

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。位置パラメータがされているシフト 1(使用左に位置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]=()

shiftも書くことができます1=()zsh

では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

2
別の(そしてandい)bashの可能性:間接変数:for ((i=2; i<=$#; i++)); do something with "${!i}"; done
グレンジャックマン

私はc ++に精通しているため、このバージョンに精通しています:)
user40780

10

shift組み込みが必要だと思います。それは名前を変更$2する$1$3$2など、

このような:

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

forループでそれをどのように実現するのか、詳しく説明していただけますか?ありがとうございました。
-user40780

1
あなたはしません- forループに入る前にそれを使用し、それから通常通り$ @をループします。shift呼び出し後、$ @はarg2_1 arg2_2 arg2_3...
ジョン

ただし、もう1つ質問があります。$ 1から$($#-2)まで(たとえば、arg_1からarg_2 _#-1まで、arg_2_#を除く)ループしたいとします。
user40780

2

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

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

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


1

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

この背後にあるストーリーは、引数バージョンと変数indirectionと組み合わされた組み込みの算術バージョンです。for$#${…}

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

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.