bashで配列値をシフトする方法


8

例として6つのマウントポイントフォルダーを構築する

/data/sdb
/data/sdc
/data/sdd
/data/sde
/data/sdf
/data/sdg

だから私たちは配列を使ってこの簡単なbashスクリプトを書きました

folder_mount_point_list="sdb sdc sdd sde sdf sdg"

folderArray=( $folder_mount_point_list )

counter=0
for i in disk1 disk2 disk3 disk4 disk4 disk5 disk6
do
folder_name=${folderArray[counter]}
mkdir /data/$folder_name
let counter=$counter+1
done

今、私たちはせずに、コードを変更したいカウンタしましょう= $カウンタ=カウンタ+ 1

次の配列値を取得するために各ループを配列にシフトすることは可能ですか?

のようなものとして

${folderArray[++]}

1
for i in disk1 disk2 disk3 disk4 disk4 disk5 disk6ループ本体内で使用されていないのは何のためですか?
RomanPerekhrest 2017

1
...そしてカウンターを使用する意味は何ですか?単純に実行しないのですfor i in "your_list_goes_here"; do mkdir /data/"$i"; doneか?
don_crissti 2017

回答:


10

総論。次のように配列を定義しても意味がありません。

folder_mount_point_list="sdb sdc sdd sde sdf sdg"
folderArray=( $folder_mount_point_list )

代わりにこれを行います:

folderArray=(sdb sdc sdd sde sdf sdg)

今あなたの質問に:

set -- sdb sdc sdd sde sdf sdg
for folder_name; do
    mkdir "/data/$folder_name"
done

または

set -- sdb sdc sdd sde sdf sdg
while [ $# -gt 0 ]; do
    mkdir "/data/$1"
    shift
done


はい@yaelは、使用することができますset -- $list_of_folders:文字列変数を移動するための方法ではありません。しかし、再びset -- "${folders[@]}"
Hauke Laging

1
なぜ使用しているのset -- ....ですか?このハックは、配列をサポートしないシェルでのみ必要です-配列をサポートするシェルでは必要ありません。 for folder_name in "${folderArray[@]}"; do ... ; done必要なのはこれだけです。
cas

たった1つの質問です。たとえば、$ {folderArray [++]}
yael

@casそれが私の答えです。私もこのsetアプローチをとっていません。
Pesa17年

14

タイトルの質問に答えるために、部分文字列/部分配列表記で配列を「シフト」できます。(shiftそれ自体は位置パラメータだけで動作します。)

$ a=(a b c d e)
$ a=("${a[@]:1}")
$ echo "${a[@]}"
b c d e

同様に、配列から最後の項目を「ポップ」するには:a=("${a[@]:0:${#a[@]} - 1}" )またはunset "a[${#a[@]}-1]"

したがって、必要に応じて、これを行うことができます。

a=(foo bar doo)
b=(123 456 789)
while [ "${#a[@]}" -gt 0 ] ; do
    echo "$a $b"
    a=("${a[@]:1}")
    b=("${b[@]:1}")
done

しかし、それは配列を破壊するので、いつものようにインデックスを付けるだけの方が良いかもしれません。または、代わりに連想配列を使用することもできます。

declare -A arr=([foo]=123 [bar]=456 [doo]=789)

4

すべての値をループするだけで、シフトは必要ありません。

folderArray=(sdb sdc sdd sde sdf sdg)

for folder in "${folderArray[@]}"; do
    mkdir "/data/$folder"
done

3

そのためのループは必要ありません。

folderArray=(sdb sdc sdd sde sdf sdg)
IFS=,
eval mkdir /data/{"${folderArray[*]}"}

トリックは、配列が添え字*"${array[*]}")で二重引用符で囲まれている場合、各配列要素の値がIFS変数の最初の文字で区切られた単一の単語に展開されることです。その後、ブレース展開メカニズムを使用/data/して各アレイメンバーにeval接続し、全体をuateします。


なぜそんなに複雑なのですか?cd /data ; mkdir "${folderArray[@]}"私は以前に同じことをしたことがありますが、このような場合はそうしません。ただし、高度なアプローチの場合は+1。
Hauke Laging

@HaukeLagingはい、mkdirコマンドの場合はそれがより簡単になります。そして、cd /data; mkdir abc def通常の人と同じように、配列さえも必要ありません。しかし、他のタスクではそれほど簡単ではないので、ループなしで各配列要素に文字列をすばやくアタッチする方法を知っておくとよいでしょう。
jimmij 2017

たった1つの質問です。たとえば、$ {folderArray [++]}
yael

1
@yael echo "${folderArray[((counter++))]}"このアプローチが本当に好きなら、あなたは何かをすることができます。内部のもの(())は数学として評価されます($前にがないことに注意してくださいcounter)。
jimmij 2017

1
そのようなシェルコードを書き始めると、perlやpythonの学習に少し時間をかけることが良い考えであることに気づきます。あなたはので、すなわちだけできるのbashで何かを、あなたが意味するものではありませんはず
cas
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.