Bashシェルスクリプトで2つの配列を連結する

2023-02-03Bash

はじめに

シェルスクリプトで変数を頻繁に使用することは多くはないが、それでも利用することはあります。
配列同士を連結する方法と注意事項についてまとめてみました。

検証環境

$ uname -moi
x86_64 MacBookPro16,1 Darwin

$ bash -version | head -n 1
GNU bash, バージョン 5.0.17(1)-release (x86_64-apple-darwin19.4.0)

配列変数の定義方法

昔、以下のエントリで取り上げたことがありますが、 declare -a というビルトインコマンドを使って、配列変数を定義することができます。( declare -a は省略可能 )

# 配列を定義
$ declare -a ARRAY

# 要素を代入
$ ARRAY[0]=11
$ ARRAY[1]=22

# 追加する場合
$ ARRAY+=(33)

配列の末尾に要素を追加する方法は ARRAY+=(33) のように記述することで追加可能です。

複数の配列変数を連結する

今回のエントリの本題にはいります。
サンプルコードを掲載します。

SUBLIST1SUBLIST2 という2つの配列変数を用意し、それらを連結し MAINLIST という変数に代入してみます。

test.sh

#!/usr/bin/env bash

# 配列の要素は4つ。2つ目の要素にはスペースを含んだ文字列が格納されている。
declare -a SUBLIST1=(
  1
  "a b"
  "c"
  4
)

# 配列の要素は3つ。3つ目の要素にはスペースを含んだ文字列が格納されている。
declare -a SUBLIST2=(
  5
  6
  "d e f"
)

MAINLIST=("${SUBLIST1[@]}" "${SUBLIST2[@]}")

# 一行ずつ出力してみる
for I in "${MAINLIST[@]}"; do
  echo "${I}"
done

実行権限を付与し実行してみます。

# 実行権限を付与
$ chmod +x test.sh

# 実行
$ ./test.sh
1
a b
c
4
5
6
d e f

配列変数の参照方法に注意

通常のプログラム言語であれば何の問題もなく動作するスクリプトです。

シェルスクリプトでは配列変数を参照する際に一点だけ気を付けなければいけないことがあります。
それはシェル変数参照の際に、以下のようにダブルクォートで囲んであるという点です。

${MAINLIST[@]}

先ほどのスクリプトに関してダブルクォートで囲まずに配列変数を参照するように書き換えて実行してみます。
(書き換え対象行は16行目と18行目になります。)

#!/usr/bin/env bash

declare -a SUBLIST1=(
  1
  "a b"
  "c"
  4
)

declare -a SUBLIST2=(
  5
  6
  "d e f"
)

MAINLIST=(${SUBLIST1[@]} ${SUBLIST2[@]})

for I in ${MAINLIST[@]}; do
  echo "${I}"
done

実行結果を見てみます。

$ ./test.sh
1
a
b
c
4
5
6
d
e
f

配列の要素を連結した結果を見ると、
先ほどは要素数が7となっていましたが、今回の例では10となっています。

二つの配列変数を連結する際にダブルクォートで囲まないと、
スペースを含む文字列要素(ここでは “a b” と “d e f” )がそれぞれ個別の要素として認識されてしまいます。

ひとこと

シェルスクリプト配列変数のすべての要素を参照する際には、以下のようにダブルクォートで囲んだフォーマットが標準形式であると覚えておきましょう。

“${LIST[@]}”

最もこれは配列変数に関わらないことではありますね。通常の変数を参照するときもダブルクォートで囲む癖をつけておくのが良いでしょう。

2023-02-03Bash