Tubo final quando o programa retorna mais de uma linha

1

Estou consultando um banco de dados mysql para o nome de um banco de dados por padrão. Atualmente, minha implementação é assim:

include_databases=$(mysql --batch --skip-column-names --execute "SHOW DATABASES LIKE 'foo%'" \
    | paste -sd ",")

O qual ativará uma lista separada por vírgulas de nomes de bancos de dados que correspondem ao padrão.

No entanto, eu realmente só espero que um nome de banco de dados seja retornado e eu acho que seria melhor errar quando o mysql retorna um resultado com 2 linhas.

Existe algo como:

include_databases=$(mysql --batch --skip-column-names --execute "SHOW DATABASES LIKE 'foo%'" \
    | __error_if_two_lines__ )
    
por Max 22.05.2017 / 03:40

2 respostas

1

Você pode usar head para extrair a primeira linha:

include_databases=$(… | head -n 1)

No entanto, isso silenciosamente ignorará quaisquer outras linhas. Você pode usar o awk para retornar um código de saída diferente se houver mais linhas:

include_databases=$(… | awk 'NR>1 {exit(2)} 1')
if [ $? -ne 0 ]; then
  echo >&2 'mysql returned multiple lines! Aborting.'; exit 2;;
fi

Ou abaixo de set -e :

include_databases=$(… | awk 'NR>1 {print "mysql returned multiple lines! Aborting." >"/dev/stderr"; exit(2)} 1')

Como alternativa, você pode armazenar a saída em uma variável e testar se ela contém uma quebra de linha. (Observe que a nova linha final do comando não está incluída na substituição do comando).

include_databases=$(…)
nl='
'
case $include_databases in
  *"$nl"*) echo >&2 'mysql returned multiple lines! Aborting.'; exit 2;;
esac

No ksh / bash / zsh, mas não no sh simples, você pode escrever isso de uma forma mais compacta.

include_databases=$(…)
if [[ "$include_databases" = *$'\n'* ]]; then
  echo >&2 'mysql returned multiple lines! Aborting.'; exit 2;;
esac
    
por 23.05.2017 / 02:28
0

Eu acho que wc é seu amigo. Use a opção -l para contar linhas, -w para contar palavras. (veja man page)

mysql --batch --skip-column-names --execute "SHOW DATABASES" | wc -w

mostra o número de bancos de dados.

por exemplo. algo parecido com isto

include_databases=$(mysql --batch --skip-column-names --execute "SHOW DATABASES")
numDB=$(echo $include_databases | wc -w)
[ $numDB -gt 1 ] && echo -n "$numDB dbs is more than "
echo "one db"

Dica: Você deve melhorar este script, porque ele usa muitos subsheels

    
por 22.05.2017 / 07:48