使用 bash 选择 mysql 查询

Orl*_*rlo 3 mysql bash

如何select使用 bash 进行 mysql 查询,使每一列都在一个单独的数组值中?

我已经尝试过以下命令,但它仅在内容是一个单词时才有效。例如: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})
Run Code Online (Sandbox Code Playgroud)

Mic*_*eim 5

Bash 默认情况下会在任何空白字符处分割字符串。首先,您的输出需要一个唯一的列标识符,您可以使用它mysql --batch来获取制表符分隔的 csv 输出。

来自 MySQL 手册页:

--批次,-B

使用制表符作为列分隔符打印结果,每行占一个新行。使用此选项,mysql 不使用历史文件。批处理模式会导致非表格输出格式和特殊字符的转义。使用原始模式可以禁用转义;请参阅 --raw 选项的说明

您希望对结果进行转义,因此不要使用--raw,否则结果数据中的制表符将再次打破循环。

要跳过第一行(列名称),您可以--skip-column-names另外使用该选项

现在您可以遍历每一行并按制表符将其拆分。您只能通过暂时覆盖 IFS 变量(内部字段分隔符)来强制 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")
Run Code Online (Sandbox Code Playgroud)

myread 函数的所有功劳都归功于Stefan Kriwanek回答

注意:您需要非常小心引号和变量分隔符。如果你只是echo $row[0]没有花括号,你会得到错误的结果

编辑 当列返回空字符串时,您仍然遇到问题,因为内部字段分隔符与任意数量的定义字符匹配:

row1\t\trow3将创建一个数组[row1,row3]而不是[row1,,row3] 我找到了一个非常好的方法来解决这个问题,更新了上面的示例。另外read可以直接将输入流分离成变量。