
Estou usando o shell bash no CentOS 7. Quero executar uma consulta MySQL a partir de um script de shell e iterar em cada linha de resultados. Se houvesse 4 linhas retornadas, pensei que poderia capturar as quatro linhas em uma matriz assim:
query="select p.id, p.ebook_id, es.id FROM ...";
echo "$query" > /tmp/query.sql
mysql -u user --password=pass db_id < /tmp/query.sql > /tmp/query.csv
linesIN=`cat /tmp/query.csv | sed 's/\t/,/g'`
arraylength=${#linesIN[@]}
echo $arraylength
No entanto, $arraylength
sempre gera saída, 1
mesmo que eu possa ver várias linhas de resultados retornadas. Como posso modificar o acima para criar corretamente uma matriz de resultados onde cada elemento da matriz representa uma linha do conjunto de resultados?
Responder1
Com o--batch
opção, mysql
deve gerar o resultado com um registro em uma linha e colunas separadas por tabulações. Você pode ler as linhas de um array comBashmapfile
e substituição de processo ou substituição de comando e atribuição de array:
mapfile results < <( mysql --batch ... < query.sql )
ou
set -f # disable globbing
IFS=$'\n' # set field separator to NL (only)
results=( $(mysql --batch ... ) )
(Observe que IFS
permanece modificado e globbing desativado depois disso.)
Então, se você quiser dividir as colunas de uma linha em algumas variáveis:
IFS=$'\t' read -r col1 col2 col2 ... <<< "${results[0]}"
Sua tarefa
linesIN=`cat /tmp/query.csv | sed 's/\t/,/g'`
não é umatribuição de matriz(falta o parêntese). Ele apenas atribui a saída da substituição do comando a uma variável de string regular. (Qualquer nova linha será incorporada lá, mas ainda será uma única string.) ${#linesIN[@]}
ainda funciona, pois em Bash/ksh matrizes de elemento único e variáveis escalares agem da mesma forma.
Responder2
Outra maneira de fazer isso seria canalizar a saída do comando para um loop while. Observe que você deseja incluir -N ou os resultados incluem o nome da coluna.
#!/bin/bash
#Script to read output from a mysql command line by line
mysql -uroot -p example -N -e "select column from table" | while IFS= read -r loop
do
echo "$loop"
done
E se você quiser apenas uma contagem, faça uma contagem select count(columnName)
e imprima os resultados.
Responder3
Se você quiser o número de linhas em um arquivo, que será igual ao número de linhas retornadas da consulta, basta usar wc
para contar o número de linhas no arquivo
arraylength=$( wc -l < /tmp/query.csv)
echo $arraylength