我正在编写一个 bash 脚本来显示各种统计信息,其中一些来自 MySQL 数据库。我遇到困难的相关代码是:
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
这显然不是我想要的(日期时间值已被分割)
根据谷歌的说法,$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)"
我认为例如(用 an 模拟您的查询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