當程式傳回超過 1 行時結束管道

當程式傳回超過 1 行時結束管道

我正在按模式查詢 mysql 資料庫以獲取資料庫名稱。目前我的實作如下所示:

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

這將傳回與模式相符的資料庫名稱的逗號分隔清單。

然而,我實際上只期望返回一個資料庫名稱,並且我認為當 mysql 返回 2 行結果時出錯會更好。

有沒有類似的東西:

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

答案1

您可以使用head提取第一行:

include_databases=$(… | head -n 1)

然而,這將默默地忽略任何進一步的行。如果有更多行,您可以使用 awk 返回不同的退出代碼:

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

或者,在set -e

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

或者,您可以將輸出儲存在變數中,並測試它是否包含換行符號。 (請注意,命令的最後一個換行符不包含在命令替換中。)

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

在 ksh/bash/zsh 中,但不是在普通 sh 中,您可以以更緊湊的方式編寫它。

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

答案2

我認為wc是你的朋友。使用選項-l來計算行數和-w單字數。 (請參閱手冊頁)

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

顯示資料庫的數量。

例如這樣的東西

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"

提示:您應該改進這個腳本,因為它使用了很多 subsheels

相關內容