프로그램이 두 줄 이상을 반환하면 파이프라인 종료

프로그램이 두 줄 이상을 반환하면 파이프라인 종료

데이터베이스 이름을 얻기 위해 스키마로 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"

팁: 이 스크립트는 많은 하위 쉘을 사용하므로 개선해야 합니다.

관련 정보