Pipe beenden, wenn das Programm mehr als eine Zeile zurückgibt

Pipe beenden, wenn das Programm mehr als eine Zeile zurückgibt

Ich frage eine MySQL-Datenbank nach dem Namen einer Datenbank nach einem Muster ab. Derzeit sieht meine Implementierung folgendermaßen aus:

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

Dadurch wird eine durch Kommas getrennte Liste mit Datenbanknamen zurückgegeben, die dem Muster entsprechen.

Allerdings erwarte ich eigentlich nur, dass ein Datenbankname zurückgegeben wird und ich denke, es wäre besser, einen Fehler auszugeben, wenn MySQL ein Ergebnis mit zwei Zeilen zurückgibt.

Gibt es sowas wie:

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

Antwort1

Sie können headzum Extrahieren der ersten Zeile Folgendes verwenden:

include_databases=$(… | head -n 1)

Dadurch werden jedoch alle weiteren Zeilen stillschweigend ignoriert. Sie können stattdessen awk verwenden, um einen anderen Exit-Code zurückzugeben, wenn weitere Zeilen vorhanden sind:

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

Oder unter set -e:

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

Alternativ können Sie die Ausgabe in einer Variablen speichern und prüfen, ob sie einen Zeilenumbruch enthält. (Beachten Sie, dass der letzte Zeilenumbruch des Befehls nicht in die Befehlsersetzung einbezogen wird.)

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

In ksh/bash/zsh, aber nicht in einfachem sh, können Sie dies kompakter schreiben.

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

Antwort2

Ich glaube, wcdas ist dein Freund. Nutze die Option -lzum Zählen von Zeilen -wund Wörtern. (siehe Manpage)

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

zeigt die Anzahl der Datenbanken an.

zB sowas

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"

Hinweis: Sie sollten dieses Skript verbessern, da es viele Unterordner verwendet

verwandte Informationen