Terminar pipe quando o programa retornar mais de 1 linha

Terminar pipe quando o programa retornar mais de 1 linha

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

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

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

No entanto, na verdade, espero que apenas um nome de banco de dados seja retornado e acho que seria melhor cometer um erro quando o mysql retornar um resultado com 2 linhas.

Existe algo como:

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

Responder1

Você pode usar headpara extrair a primeira linha:

include_databases=$(… | head -n 1)

No entanto, isso ignorará silenciosamente 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, sob set -e:

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

Alternativamente, 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

Em ksh/bash/zsh, mas não em 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

Responder2

Acho que wcé seu amigo. Use a opção -lpara contar linhas, -wpara contar palavras. (veja a página de manual)

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

mostra o número de bancos de dados.

por exemplo, algo assim

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, pois ele usa muitos subsheels

informação relacionada