256bitの殺人メニュー

インフラエンジニアだったソリューションアーキテクトなくわののブログ。こちらのBlogは個人の意見となっていて会社とは全く関係ありません。お約束です。[twitter:@kuwa_tw]めんどくさがりが重い腰を上げて何かをアウトプットすることにどれほどの意味があるのかを試してみたいブログでもある。

linuxのbashで配列やったりなんだりする

シェルスクリプト書いてて、わざわざ文字チェックだとか、変換とかやるの面倒くさいなぁと思ってたらtypeset便利じゃん使ってなかったわ−ってなった。

typesetとは

bashの組み込みコマンドで、変数の宣言を行うためのサブコマンドです。
配列を定義したり、変数に型の概念をもたせたりもします。


以下bash の manから抜粋。

オプション 意味
-a はそれぞれ配列変数として定義。
-f 定義されている関数名を表示します
-i 変数を整数として扱います。変数に値が代入された時に算術式評価 ( 算術式評価を参照) が実行されます。
-r 読み込み専用にします。これ以降、代入文を用いて値を代入したり unset したりできなくなります。
-x 変数をエクスポートする。export HOGEHOGE と同意
-u 入っている値が小文字だった場合に、大文字に変換する
-l 入っている値が大文字だった場合に、小文字に変換する

例1:typesetを用いた配列

配列処理はあるとやはり便利だなぁと。

コード
#!/bin/bash

# テスト用
CNT=0

# 配列定義
typeset -a ARRAY
ARRAY=(1 2 3 4 5)
typeset -p ARRAY
# seqと組み合わせたりexprしたりしてループ回す
for i in `seq 0 4`
do
  echo "ARRAY[${i}]: ${ARRAY[${i}]}"
done
実行結果
declare -a ARRAY='([0]="1" [1]="2" [2]="3" [3]="4" [4]="5")'
ARRAY[0]: 1
ARRAY[1]: 2
ARRAY[2]: 3
ARRAY[3]: 4
ARRAY[4]: 5

例2:typesetを用いた大文字、小文字変換

入力バリデーション等にしようすると、大文字、小文字を区別しない様になるので煩雑でなくなります。

コード
#!/bin/bash

# 大文字に変換する文字型
typeset -u UC
UC="abcde"
typeset -p UC
echo ${UC}

echo ""

# 小文字に変換する文字型
typeset -l LC
LC="FGHIJ"
typeset -p LC
echo ${LC}

echo ""

# 小文字大文字に依存しないバリデーション
if [ x"${UC}" == x"ABCDE" ]
then
    echo "OK"
else
    echo "NG"
fi
実行結果
declare -u UC="ABCDE"
ABCDE

declare -l LC="fghij"
fghij

OK

例3:typesetを用いたリードオンリー変数の作成

各種スクリプトの設定等に使用すると、どこで設定が書き換わってるかわからなくなる事を避けられます。

コード
#!/bin/bash

# READONLY型
typeset -r RO='readonly'
echo ${RO}
typeset -p RO
RO='write'              # ここでエラーになる。
echo ${RO}
実行結果
readonly
declare -r RO="readonly"
typeset_test.sh: 行 43: RO: 読み取り専用の変数です
readonly

例4:typesetを用いた整数型変数の作成

コード
#!/bin/bash

# INT型
typeset -i INT=100
echo ${INT}
typeset -p INT
INT='write'     # 入れても0になっている
echo ${INT}
実行結果
100
declare -i INT="100"
0

番外編:prinfを用いた整数型変数の作成(各種右寄せ、左寄せ、0埋め)

処理系によっては、これらもtypesetで出来る物もあるのですが、LinuxBashに実装されているtypsetではできないので番外編として載せておきます。
ファイル名、ホスト名など、0パディングされているものも多いので良く使います。

コード
#!/bin/bash

# 番外編 各種右寄せ、左寄せ、0埋め
FILENO=1
# 右寄せ
printf "[%3d]\n" ${FILENO}
# 左寄せ
printf "[%-3d]\n" ${FILENO}
# 0埋め
printf "[%03d]\n" ${FILENO}
実行結果
[  1]
[1  ]
[001]

まとめ

これらを利用して、処理を楽にしたり、バリテーション処理を簡素にしてみるのも読みやすいスクリプトの実装のためには良いと思います。
ただし、Linux依存になってしまうのでその点はイカンですが><


そしてこれ以上やるならLL言語で書く事も考慮に入れたほうがよいかと思います。
以上!なんかマジメな事言っちゃった気もするけどドヤ顔してないです(ドヤァ


[改訂新版] シェルスクリプト基本リファレンス  ??#!/bin/shで、ここまでできる (WEB+DB PRESS plus)

[改訂新版] シェルスクリプト基本リファレンス  ??#!/bin/shで、ここまでできる (WEB+DB PRESS plus)