2014-01-14 113 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

谢谢!它为我节省了时间。 –