Case 문의 인라인 그룹화 명령이 작동하지 않습니다: 예기치 않은 마커 ";;" 근처에 구문 오류가 있습니다.

Case 문의 인라인 그룹화 명령이 작동하지 않습니다: 예기치 않은 마커 ";;" 근처에 구문 오류가 있습니다.

내 bash 스크립트에서 매개변수를 구문 분석합니다. 특정 패턴 없이 "path"라는 하나의 매개변수만 허용하려고 합니다. 대소문자에 맞지 않는 다른 매개변수는 스크립트를 종료하게 합니다. 예는 다음과 같습니다.

#!/bin/bash
while [ "$#" -gt 0 ]; do
    case "$1" in
        -v|--verbose) verbose=1 ;;
        -h|--help)
            echo "Usage: $(basename "$0") [OPTIONS] [PATH]"
            echo "Does something interesting with the given path."
            echo ""
            echo "OPTIONS"
            echo "  -v,   --verbose                 Prints verbose information."
            echo "  -h,   --help                    Prints this help message."
            exit 0
            ;;
        *) { test -z $path && path=$1 } || { echo "Invalid command line flag $1" >&2 && exit 1 } ;;
    esac
    shift
done

그러나 이 줄은 { test -z $path && path=$1 } || { echo "Invalid command line flag $1" >&2 && exit 1 } ;;다음과 같은 경우 실패합니다.

myscript: line 14 syntax error near unexpected token `;;'
myscript: line 14: `           *) { test -z $path && path=$1 } || { echo "Invalid command line flag $1" >&2 && exit 1 } ;;'

간단하게 if-else 문을 작성할 수 있다는 것을 알고 있지만 인라인으로 그룹화할 수 없는 이유가 궁금합니다. 중괄호를 제거하면 exit 1항상 도달합니다.

답변1

한 줄 명령 그룹 내의 명령 목록은 세미콜론으로 끝나야 합니다. { list; }그렇지 않으면{ list }

예를 들어,

$ bash -c 'case $1 in *) { echo foo && echo bar } ;; esac' bash baz
bash: -c: line 0: syntax error near unexpected token `;;'
bash: -c: line 0: `case $1 in *) { echo foo && echo bar } ;; esac'

실패하다,

$ bash -c 'case $1 in *) { echo foo && echo bar; } ;; esac' bash baz
foo
bar

효과가 있었습니다.

바라보다명령 목록과 } 사이의 구분 기호그리고 bash 매뉴얼 섹션명령 그룹화.

답변2

이전 답변과 의견은 주요 오류 원인을 다룹니다.

나는 여러 줄 사용 메시지를 스크립트의 다른 부분(예: 서브루틴)으로 이동하고 절에서 -h|-help)간단히 서브루틴을 호출하도록 제안을 게시했습니다.

USAGE () {
  echo "This is the first line of my usage message"
  echo "This is another line"
  echo "Etc."
}

(farther down the script)

case "$1" in
    -v|--verbose) verbose=1 ;;
       -h|--help) USAGE ; exit 0 ;;
               *) # your code here ;;
esac

또는 여기 문서를 사용하여 여러 줄의 사용법 메시지를 문자열 변수로 조합한 다음 Case 문 절을 사용하여 해당 변수를 표시하고 종료할 수 있습니다.

# fill $USAGE with a here document that isn't indented
USAGE=$(cat - <<EOUSAGE
Usage: $(basename "$0") [OPTIONS] [PATH]
Does something interesting with the given path.

OPTIONS
  -v,   --verbose                 Prints verbose information.
  -h,   --help                    Prints this help message.
EOUSAGE
)  # USAGE=$( ... ) ends here

(farther down the script)

case "$1" in
  -v|--verbose) verbose=1 ;;
     -h|--help) echo "$USAGE" ; exit 0 ;;
             *) # your code here ;;
esac

여러 줄로 된 메시지를 작성하는 것이 여러 개의 echo 명령을 작성하는 것보다 훨씬 덜 혼란스럽고 텍스트의 빈 줄이나 따옴표가 문제가 되지 않기 때문에 여기서는 문서화 방법을 사용하는 것을 선호합니다. 또한 들여쓰기가 되어 있지 않기 때문에 터미널 창에서 각 줄이 얼마나 멀리 확장되는지 확인할 수 있으며 더 긴 줄은 가독성을 높이기 위해 줄 바꿈될 수 있습니다.

관련 정보