如何使用制表符作为分隔符将 bash 中的字符串解析为变量并保留空格?

如何使用制表符作为分隔符将 bash 中的字符串解析为变量并保留空格?

我正在编写一个 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

相关内容