2014-01-14 3 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 опции

Вы хотите результат быть экранирован, поэтому не используйте --raw, в противном случае символ табуляции в данном результате будет разорвать цикл снова.

Чтобы пропустить первый ряд (имена столбцов), вы можете использовать опцию --skip-column-names в дополнение

Теперь вы можете пройти через каждую линию и разделить его на символ табуляции. Вы можете заставить bash разбиваться на вкладку только путем переопределения переменной IFS (Internal Field Separator) временно.

Пример

# 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 answer по Stefan Kriwanek

Внимание: Вы должны быть очень осторожны с цитатами и переменными разделителей. Если вы просто echo $row[0] без фигурных скобок, вы получите неверный результат

EDIT У вас еще есть проблема, когда столбец возвращает пустую строку, так как внутренний разделитель полей совпадает с любым количеством определенного полукокса:

row1\t\trow3 создаст массив [row1,row3] вместо [row1,,row3] Я нашел очень хороший подход, чтобы исправить это, обновленный пример выше. Также чтение может напрямую разделять входной поток на переменные.

+0

Это не так просто, как я думал, это будет - держись за фактически работающее решение –

+0

ОК, извините за путаницу, пример сейчас работает.Убедитесь, что вы используете фигурные скобки, это важно –

+0

Спасибо! Это спасло меня. –

Смежные вопросы