2014-01-14 114 views
3

如何select mysql查詢與bash因此每列將在一個單獨的數組值?選擇mysql查詢與bash

我試過下面的命令,但它只適用於內容是一個單詞的情況。例如: id = 11,text = hello,important = 1

如果我有一篇文章,例如text。代碼將無法正常工作。我想我可以使用cut -f -d,但如果「文本」包含特殊字符它也不會工作。

while read -ra line; do 
    id=$(echo "${line[1]}") 
    text=$(echo "${line[2]}") 
    important=$(echo "${line[3]}") 

    echo "id: $id" 
    echo "text: $text" 
    echo "important: $important" 

done < <(mysql -e "${selectQ}" -u${user} -p${password} ${database} -h ${host}) 

回答

3

Bash默認情況下會將字符串分割爲任何空格字符。首先,您需要輸出的唯一列標識符,您可以使用mysql --batch來獲取製表符分隔的csv輸出。

從MySQL的手冊頁:

--batch,-B使用選項卡作爲列分隔符,用在新行的每一行

打印結果。使用這個選項,mysql不會使用歷史文件。 批處理模式導致非表格輸出格式和特殊字符轉義。通過使用原始模式可能會禁用轉義;請參閱--raw選項的說明

您希望結果被轉義,因此請勿使用--raw,否則結果數據中的製表符會再次打破循環。

要跳過第一行(列名),你可以使用選項--skip-column-names除了

現在,你可以通過每個線走路,製表符拆呢。 只能通過臨時覆蓋IFS變量(Internal Field Separator)來強制bash按標籤分割。

# myread prevents collapsing of empty fields 
myread() { 
    local input 
    IFS= read -r input || return $? 
    while (($# > 1)); do 
     IFS= read -r "$1" <<< "${input%%[$IFS]*}" 
     input="${input#*[$IFS]}" 
     shift 
    done 
    IFS= read -r "$1" <<< "$input" 
} 


# loop though the result rows 
while IFS=$'\t' myread id name surname url created; do 
    echo "id: ${id}"; 
    echo "name: ${name}"; 
    echo "surname: ${surname}"; 
    echo "url: ${url}"; 
    echo "created: ${created}"; 
done < <(mysql --batch --skip-column-headers -e "SELECT id, name, surname, url, created FROM users") 

myread功能所有學分this answerStefan Kriwanek

注意: 你必須非常小心引號和可變的分隔符。 如果你只是echo $row[0]沒有大括號,你會得到錯誤的結果

編輯 你還有一個問題,當一列,因爲內場分離器相匹配的定義字符的任意量返回空字符串:

row1\t\trow3將創建一個數組[row1,row3]而不是[row1,,row3] 我發現了一個很好的方法來解決這個問題,更新了上面的例子。 也讀取可以直接將輸入流分離成變量。

+0

它並不像我想象的那樣簡單 - 堅持實際工作的解決方案 –

+0

好的,對於混淆抱歉,示例正在工作。確保你使用大括號,這很重要 –

+0

謝謝!它爲我節省了時間。 –