Bash シェルスクリプトで配列要素を 1 つ 1 つ置換する

Bash

はじめに

Bash では、配列を作成し、変数に代入できます。

例えば、1〜3 の要素を持つ配列変数は以下のように定義できます。

# 以下のいずれかで定義できる
declare -a NUMS=(11 12 13)

typeset -a NUMS=(11 12 13)

NUMS=(11 12 13)

ここで、 変数 NUMS の各要素の 1 という文字列を x に置換したいとします。

ループで置換していけばよいのですが、ループを記述子なくても置換できます。

検証環境

$ uname -moi
aarch64 aarch64 GNU/Linux

$ head -n 3 /etc/os-release
PRETTY_NAME="Ubuntu Kinetic Kudu (development branch)"
NAME="Ubuntu"
VERSION_ID="22.10"

$ bash -version | head -n 1
GNU bash, バージョン 5.2.0(1)-release (aarch64-unknown-linux-gnu)

変数の置換記法を使う

Bash には 変数を参照する際にパターンマッチで置換する機能があります。

# 変数 HELLO を定義
$ declare HELLO="My name is genzouw"

ここで作成した変数 HELLO を、参照するタイミングで置換できます。

# genzouw から taro に出力内容がかわっている
$ echo ${HELLO/genzouw/taro}
My name is taro

${変数/検索文字列/置換文字列} の形式で記述します。

配列変数に対して展開時の置換機能を適用する

先の例では、「文字列」変数に対して置換しました。

「配列」変数に対して同様の置換記法を利用すると、配列の各要素が個別に置換されます。

まずは配列変数を作成します。

$ declare -a WORDS=(ABC BCA CAB ACB)

置換してみます。配列変数を参照する際の記法に注意です。

$ echo ${WORDS[@]/A/@}
@BC BC@ C@B @CB

このようにすべての要素が置換されました。

前方一致で置換させるためには置換文字列の最初に # を記述します。

$ echo ${WORDS[@]/#A/@}
@BC BCA CAB @CB

後方一致で置換させるためには置換文字列の最初に # を記述します。

$ echo ${WORDS[@]/%A/@}
ABC BC@ CAB ACB

このように記述することで、ループを書かずに配列の要素を1つずつ置換していくことができます。

シェルスクリプトや関数の引数に対しても各要素の置換ができる

配列変数の各要素を置換した記法ですが、シェルスクリプトや関数の引数に対しても適用できます。

# 受け取った引数からカンマを取り除く
function exclude_comma {
  echo ${@/,/}
}

$ exclude_comma 1,234 567 89,100
1234 567 89100

# カンマを取り除くはループ外で実行
function sum {
  declare -i sum=0
  for n in ${@/,/}; do ((sum+=n)); done
  echo $sum
}

$ sum 1,234 567 89,100
183604

ひとこと

では、今回紹介した記法を使うのかというとほとんど使った事がありません。

Bash