私はMySQLデータベースのいくつかの統計を含むさまざまな統計を表示するためのbashスクリプトを書いています。問題のある関連コードは次のとおりです。
read min max rows <<< $(mysql $dbDatabase -u $dbUser -p$dbPass -B -N -e \
"SELECT MIN(\`DateTime\`), MAX(\`DateTime\`), COUNT(*) FROM $dbTable")
echo "Min Date:" $min
echo "Max Date:" $max
echo "Total Rows:" $rows
実行結果は次のとおりです。
Min Date: 2013-03-18
Max Date: 20:30:00
Total Rows: 2014-07-31 14:30:00 11225139
これは明らかに私が望むものではありません(日付/時間値が分割されています)。
Googleによると、$IFS
私の質問に答える必要があります。残念ながら、まだ結果を正しく解析できません。
IFS=$'\t' read min max rows <<< ...
結果:
Min Date: 2013-03-18 20:30:00 2014-07-31 14:30:00 11225139
Max Date:
Total Rows:
msyql -B | tr $'\t' 'X'
フィールドがタブで区切られていることを視覚的に証明するので、これは奇妙であることがわかりました。
回避策として、次の操作を実行して目的の出力を生成できます。
read min max rows <<< $(mysql $dbDatabase -u $dbUser -p$dbPass -B -N -e \
"SELECT MIN(\`DateTime\`), MAX(\`DateTime\`), COUNT(*) FROM $dbTable" \
| tr ' ' '.')
min=$(tr '.' ' ' <<< $min)
max=$(tr '.' ' ' <<< $max)
echo "Min Date:" $min
echo "Max Date:" $max
echo "Total Rows:" $rows
しかし、これはエレガントに見えず、「Unix方式」とは見えません。
私が間違っているのか、なぜ$IFS
動作しないのか、きれいで(ハッキングされていない)理解しやすいコードを持つ正しい使い方が何であるかを知っている人はいますか?
答え1
コマンド置換の結果の周りに引用符が必要です。"$(command)"
たとえば(クエリをシミュレートする場合echo
)。
$ IFS=$'\t' read min max rows <<< "$(echo -e "Wed Jul 30 15:40:38 EDT 2014\tThu Jul 31 15:40:38 EDT 2014\t27")"
$ echo "$min"; echo "$max"
Wed Jul 30 15:40:38 EDT 2014
Thu Jul 31 15:40:38 EDT 2014
または(より直接的に)使用プロセスの交換代わりに
$ IFS=$'\t' read min max rows < <(echo -e "Wed Jul 30 15:40:38 EDT 2014\tThu Jul 31 15:40:38 EDT 2014\t27")
$ echo "$min"; echo "$max"
Wed Jul 30 15:40:38 EDT 2014
Thu Jul 31 15:40:38 EDT 2014