bash array
bash では、他のプログラミング言語と同様に array(配列)を使用することが出来ます。ここでは、RHEL8 を例に取り、代表的な associative array(連想配列)の操作方法をご紹介します。
$ cat /etc/redhat-release
Red Hat Enterprise Linux release 8.8 (Ootpa)
$ bash --version
GNU bash, version 4.4.20(1)-release (x86_64-redhat-linux-gnu)
Copyright (C) 2016 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software; you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
Create & Manipulate associative array
以下のような方法で associative array を作成することが出来ます。
$ declare -A ASSO_A=([a]="aaa" [b b]="bbb" [c@+c]="ccc")
$ declare -p ASSO_A
declare -A ASSO_A=([c@+c]="ccc" [a]="aaa" ["b b"]="bbb" )
代表的な配列要素(element)の操作には、以下があります。
# Number of elements
$ echo ${#ASSO_A[@]}
3
# Index List
$ echo "${!ASSO_A[@]}"
c@+c a b b
$ for I in "${!ASSO_A[@]}"; do echo "$I : ${ASSO_A[$I]}"; done
c@+c : ccc
a : aaa
b b : bbb
# Get All Elements
$ echo ${ASSO_A[@]}
ccc aaa bbb
$ echo ${ASSO_A[*]}
ccc aaa bbb
# Get Specific Elements
$ echo ${ASSO_A[c@+c]}
ccc
$ echo ${ASSO_A[b b]}
bbb
Slice 操作ではエラーが発生しませんが、期待した結果にならない場合があります。
# Get Elements with Slice #1
$ echo ${ASSO_A[@]:-1}
ccc aaa bbb
$ echo ${ASSO_A[@]:0}
ccc aaa bbb
$ echo ${ASSO_A[@]:1}
ccc aaa bbb
$ echo ${ASSO_A[@]:2}
aaa bbb
$ echo ${ASSO_A[@]:3}
bbb
$ echo ${ASSO_A[@]:4}
# Get Elements with Slice #2
$ echo ${ASSO_A[@]:-1:1}
ccc aaa bbb
$ echo ${ASSO_A[@]:0:1}
ccc
$ echo ${ASSO_A[@]:1:1}
ccc
$ echo ${ASSO_A[@]:2:1}
aaa
$ echo ${ASSO_A[@]:3:1}
bbb
$ echo ${ASSO_A[@]:4:1}
Element の追加・削除等も可能です。
# Add Elements
$ ASSO_A[z zz z]="Additional Element"
$ declare -p ASSO_A
declare -A ASSO_A=(["z zz z"]="Additional Element" [c@+c]="ccc" [a]="aaa" ["b b"]="bbb" )
$ echo ${!ASSO_A[@]}
z zz z c@+c a b b
# Delete Elements
$ unset ASSO_A["b b"]
$ declare -p ASSO_A
declare -A ASSO_A=(["z zz z"]="Additional Element" [c@+c]="ccc" [a]="aaa" )
$ echo ${!ASSO_A[@]}
z zz z c@+c a
ファイルからの入力でも associative array を作成することが出来ます。以下のファイルを使用してみます。
$ cat associative_input.txt
[A]="aa"
[B B]="bb"
[C Cc C]="cc"
[D-.@]="dd"
$ declare -A ASSO_B
$ eval ASSO_B=( $(cat associative_input.txt) )
$ declare -p ASSO_B
declare -A ASSO_B=([D-.@]="dd" ["C Cc C"]="cc" [A]="aa" ["B B"]="bb" )
$ for I in "${!ASSO_B[@]}"; do echo "$I : ${ASSO_B[$I]}"; done
D-.@ : dd
C Cc C : cc
A : aa
B B : bb
コマンド出力からでも associative array を作成することが出来ます。以下のコマンドを使用してみます。
$ systemctl list-timers
NEXT LEFT LAST PASSED UNIT ACTIVATES
Tue 2023-11-14 21:10:00 JST 6min left Tue 2023-11-14 21:00:17 JST 2min 56s ago sysstat-collect.timer sysstat-collect.service
Wed 2023-11-15 00:00:00 JST 2h 56min left Tue 2023-11-14 09:05:39 JST 11h ago mlocate-updatedb.timer mlocate-updatedb.service
Wed 2023-11-15 00:00:00 JST 2h 56min left Tue 2023-11-14 09:05:39 JST 11h ago unbound-anchor.timer unbound-anchor.service
Wed 2023-11-15 00:07:00 JST 3h 3min left n/a n/a sysstat-summary.timer sysstat-summary.service
Wed 2023-11-15 18:01:58 JST 20h left Tue 2023-11-14 18:01:58 JST 3h 1min ago systemd-tmpfiles-clean.timer systemd-tmpfiles-clean.service
5 timers listed.
Pass --all to see loaded but inactive timers, too.
Timer Unit (UNIT) を Key に、次回時刻 (NEXT) を Value にして作成してみます。
associative array 用に awk で文字列を加工します。
$ systemctl --no-legend list-timers | awk '{print "["$(NF-1)"]=\""$1,$2,$3,$4"\""}'
[sysstat-collect.timer]="Tue 2023-11-14 21:10:00 JST"
[mlocate-updatedb.timer]="Wed 2023-11-15 00:00:00 JST"
[unbound-anchor.timer]="Wed 2023-11-15 00:00:00 JST"
[sysstat-summary.timer]="Wed 2023-11-15 00:07:00 JST"
[systemd-tmpfiles-clean.timer]="Wed 2023-11-15 18:01:58 JST"
上記を元に associative array を作成することができます。
$ declare -A ASSO_C
$ eval ASSO_C=( $(systemctl --no-legend list-timers | awk '{print "["$(NF-1)"]=\""$1,$2,$3,$4"\""}') )
$ declare -p ASSO_C
declare -A ASSO_C=([systemd-tmpfiles-clean.timer]="Wed 2023-11-15 18:01:58 JST" [unbound-anchor.timer]="Wed 2023-11-15 00:00:00 JST" [mlocate-updatedb.timer]="Wed 2023-11-15 00:00:00 JST" [sysstat-collect.timer]="Tue 2023-11-14 21:10:00 JST" [sysstat-summary.timer]="Wed 2023-11-15 00:07:00 JST" )
$ for I in "${!ASSO_C[@]}"; do echo "$I : ${ASSO_C[$I]}"; done
systemd-tmpfiles-clean.timer : Wed 2023-11-15 18:01:58 JST
unbound-anchor.timer : Wed 2023-11-15 00:00:00 JST
mlocate-updatedb.timer : Wed 2023-11-15 00:00:00 JST
sysstat-collect.timer : Tue 2023-11-14 21:10:00 JST
sysstat-summary.timer : Wed 2023-11-15 00:07:00 JST