Bash

如何使用製表符作為分隔符將 bash 中的字元串解析為變數並保留空格?

  • July 31, 2014

我正在編寫一個 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

這顯然不是我想要的(DateTime 值已被拆分)

根據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不適合我,正確的用法是擁有乾淨(非hacky)和可理解的程式碼?

您需要在命令替換的結果周圍加上引號,即"$(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

引用自:https://unix.stackexchange.com/questions/147743