Bashシェルスクリプト上での `read` コマンドの便利な使い方いろいろ

2023-02-15Bash,CentOS,Linux,Ubuntu

Bashシェルスクリプトで標準入力からの情報を取り扱う read コマンドと declare コマンドを組み合わせると便利read コマンドについて触れたついでに、 read コマンドの便利な使い方にも触れておきます。

検証環境

$ 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>

変数をバラす

read コマンドは 区切り文字を元に標準入力からのデータをばらして変数に投入してくれる という機能があるので、それを上手に使うと変数をバラすのが楽になります。

例)年、月、日を別の変数に代入する

date コマンドを3回実行すれば取得できます。

# 年、月、日を取得
$ Y="$(date +%Y)"
$ M="$(date +%m)"
$ D="$(date +%d)"

# 確認してみる
$ echo "$Y と $M と $D"
2019 と 02 と 07

date コマンドの実行結果を read コマンドに 食わせることで同じことができます。

# dateの実行結果を標準入力として渡す
$ read Y M D < <(date +'%Y %m %d')

# 確認してみる
$ echo "$Y と $M と $D"
2019 と 02 と 07

ちなみに以下のコマンドではうまくいきません。

# dateの実行結果を標準入力として渡す
$ date +'%Y %m %d' | read Y M D

# 正しく表示されない!
$ echo "$Y と $M と $D"
 と  と

パイプで繋いだコマンドは、現在実行中のBashプロセスの子プロセスとなります。
上記例では Y / M / D のそれぞれの変数は、子プロセス終了とともに破棄されてしまうので、後続処理では参照できません。

ログにタイムスタンプを表示

Linuxサーバ上でログ監視やリソース監視をすることがあります。

tail -f を使って監視を行う場合に、タイムスタンプが出力されていない場合があります。
(データが正しく連携されてきたかな?みたいなのを眺めてるときに、データそのものに書き込み時間のような情報がない場合もあります。)

以下のようにすれば、 tail -f で逐次流れてきたデータに対して、タイムスタンプを付与できます。
(本当は書き込みタイミングとの時間のずれがあるが、ズレが許容できるなら便利な方法)

# テストデータのために、1秒ごとにランダムな数値を出力するファイルを作成

$ while true; do
  echo $RANDOM;
  sleep 1;
done > test.log &

# この状態だと、いつ書き込まれたかわからない
$ tail -f test.log
17434
15657
21714
10082
12302
30370
5088

# タイムスタンプが表示されている。($REPLYとは?後述)
$ tail -f test.log | while read; do
  echo "[$(date)] $REPLY";
done
[木  2  7 04:52:12 JST 2019] 28710
[木  2  7 04:52:13 JST 2019] 31432
[木  2  7 04:52:14 JST 2019] 3341
[木  2  7 04:52:15 JST 2019] 475
[木  2  7 04:52:16 JST 2019] 27598
[木  2  7 04:52:17 JST 2019] 22992
[木  2  7 04:52:18 JST 2019] 31265
[木  2  7 04:52:19 JST 2019] 15051
[木  2  7 04:52:20 JST 2019] 27332
[木  2  7 04:52:21 JST 2019] 7600
[木  2  7 04:52:22 JST 2019] 14547
[木  2  7 04:52:23 JST 2019] 16859
[木  2  7 04:52:24 JST 2019] 14108
[木  2  7 04:52:25 JST 2019] 13379
[木  2  7 04:52:26 JST 2019] 10708
[木  2  7 04:52:27 JST 2019] 20908
[木  2  7 04:52:28 JST 2019] 10264
[木  2  7 04:52:29 JST 2019] 28112
[木  2  7 04:52:30 JST 2019] 8908

いきなり出てきた変数 REAPLY について。
read コマンドが引数無しで呼び出された場合、変数 REPLY に値が代入されます。

メッセージを表示し、ユーザの入力を促す

インタラクティブなスクリプトを書くときに、 read -p コマンドでメッセージを表示し入力を促すことができます。

$ read -p '合言葉をどうぞ! > '
合言葉をどうぞ! > hello

$ echo "$REPLY"
hello

入力された合言葉が見えるのはさすがに、という場合もあります。
read -s -p コマンドで入力された内容が表示されないようにできます。

$ read  -s -p '合言葉をどうぞ! > '; echo
合言葉をどうぞ! >

$ echo "$REPLY"
hello

echo コマンドを追加しているのは、入力情報がエコーされないので、入力最後の改行が表示されず、プロンプトがおかしな場所に表示されるのを回避するため。

2023-02-15Bash,CentOS,Linux,Ubuntu