Bashシェルスクリプトで標準入力からの情報を取り扱う `read` コマンドと `declare` コマンドを組み合わせると便利
Bashのビルトインコマンド “declare” の使い方紹介(その1) | ゲンゾウ用ポストイット で 配列型の変数 について触れ、その後
Bashのビルトインコマンド “declare” の使い方紹介(その2) | ゲンゾウ用ポストイット で 大文字専用の変数 あるいは 小文字専用の変数 について取り扱ったので、少しだけ関係する read
ビルトインコマンドについても触れておく。
declare
と read
を組み合わせるとデータ操作が便利になるケースが有る。
read
ビルトインコマンドとは?
簡単に列挙。
- 標準入力を読み、一行ずつ読み込む
- 終了コードは、行を読み込めたときは 0、 読み込めなかったとき (EOF も含む) は 1
- ループの終了判定に使うことができる
- 引数にシェル変数名が指定し、読み込んだ行を変数に格納する
- 行末の改行は削除される
ベーシックな使い方として、ファイルの内容を1行ずつ読み込む処理として使われる。
while
コマンドと一緒にループ処理を記述する際に使われる。
検証環境
$ uname -a
Darwin NP178 18.2.0 Darwin Kernel Version 18.2.0: Mon Nov 12 20:24:46 PST 2018; root:xnu-4903.231.4~2/RELEASE_X86_64 x86_64 i386 MacBookPro11,4 Darwin
$ bash -version
GNU bash, バージョン 5.0.2(1)-release (x86_64-apple-darwin18.2.0)
Copyright (C) 2019 Free Software Foundation, Inc.
ライセンス GPLv3+: GNU GPL バージョン 3 またはそれ以降 <http://gnu.org/licenses/gpl.html>
事前準備(サンプルデータ作成)
適当なデータを作成
$ cat <<EOF >> data.csv
a,b,c
d,E,F
G,h,i
1,2,3
4,5,X
EOF
# ファイルができたか確認
$ cat data.csv
1行ずつ読み込み、変数に代入
cat
でいいよね、というぐらいに簡単な処理。
$ cat data.csv | while read line; do
echo "$line"
done
a,b,c
d,E,F
G,h,i
1,2,3
4,5,X
1行ずつ読み込み、列ごとにばらして変数に代入
これも cut
コマンドでいいよね、というぐらいに簡単な処理ではあるが。
# 列の区切り文字として、 "," を使うように変更
$ cat data.csv | while IFS=, read c1 c2 c3; do
# 今回は2列目だけを出力させてみる
echo "$c2"
done
b
E
h
2
5
ポイントは IFS=,
の部分。 read
コマンド実行の際に、今回は環境変数 IFS
として文字列 ,
を設定して実行することを指示している。
ちなみに、環境変数 IFS
はデフォルトでは スペース と タブ となっている。
つまり、 read
コマンドはデフォルト挙動では スペース と タブ を列の区切り文字として扱う。
# このように空白とタブが出力される(わからない??)
$ echo "[$IFS]"
[
]
1行ずつ読み込み、列ごとにばらして変数に代入(ただし、1列目だけでいい)
$ cat data.csv | while IFS=, read c1 x; do
# 今回は1列目だけを出力させてみる
echo "$c1"
done
a
d
G
1
4
$ cat data.csv | while IFS=, read c1 x; do
# xを見ると、2列目以降全て化膿されている
echo "$x"
done
b,c
E,F
h,i
2,3
5,X
不要な行は x
という変数に突っ込んで捨てる。
x
の部分を _
と記述されているコードをよく見る。
$ cat data.csv | while IFS=, read c1 _; do
# 今回は1列目だけを出力させてみる
echo "$c1"
done
この場合、 $_
は参照できない。(なぜだろう??)
1行ずつ読み込み、列ごとにばらして配列型の変数に代入
ようやく declare
と関連するはなしにきた。
read
で読み込んだ列データを配列型の変数に代入することができる。
# 配列型の変数を宣言
$ declare -a COLS
# `-a` オプション付きで read する
$ cat data.csv | while IFS=, read -a COLS; do
# 今回は2列目だけを出力させてみる
echo "${COLS[1]}"
done
c
F
i
3
X
Bashのビルトインコマンド “declare” の使い方紹介(その1) | ゲンゾウ用ポストイット で取り上げたとおり、 declare -a
で配列型の変数を宣言できる。
read -a
で 配列型の変数に列データを格納し取り扱うことができる。
特に列が大量にある csv データや tsv データを取り扱うときに便利。
read
コマンドの後ろに変数を30も40も書いていられないし、 sed
で処理するのも面倒だったりする場合がある。
更に発展形。 配列かつ大文字専用 の変数に read
してみる。( Bashのビルトインコマンド “declare” の使い方紹介(その2) | ゲンゾウ用ポストイット )
$ declare -u -a UPPER_COLS
$ cat data.csv | while IFS=, read -a UPPER_COLS; do
# 今回は2列目だけを出力させてみる
echo "${UPPER_COLS[1]}"
done
B
E
H
2
5
ちゃんと値が大文字に変換されて出力されている。
さいごに
時間が足りないwww
また後日 read
コマンドの便利な使い方を取り上げます。
ディスカッション
コメント一覧
まだ、コメントがありません