||와 함께 여러 명령을 사용하지 않는 이유 또는 && 조건부 작업?


12

이것은 쉘 (bash, dash) 프롬프트에서 작동합니다.

[ -z "" ] && echo A || echo B
A

그러나 POSIX 쉘 스크립트 를 작성하려고하는데 다음과 같이 시작됩니다.

#!/bin/sh

[ "${#}" -eq 1 ] || echo "Invalid number of arguments, expected one."; exit 1

readonly raw_input_string=${1}

[ -z "${raw_input_string}" ] && echo "The given argument is empty."; exit 1

그리고 나는 왜 그런지 모르겠지만 메시지를받지 못했습니다 .

주어진 인수가 비어 있습니다.

다음과 같이 스크립트를 호출하면

./test_empty_argument ""

왜 그런 겁니까?


5
참조 변수가 비어 있거나 공백이 포함 된 경우 내가 테스트 할 수 있습니까? 변수가 비어 있거나 설정되지 않았거나 공백 만 포함되어 있는지 테스트하는 방법 이 질문의 문제는 그와 아무 관련이 없습니다.
— ilkkachu

1
그냥 사용하십시오if [ X”” = X”$var” ] ; then echo isempty ; fi
— user2497

3
@ user2497 지난 20 년 동안 릴리스 된 쉘에서 사용할 이유가 없습니다. 그것은 오래되고 버그가 많은 껍질에 대한 해결 방법입니다.
— chepner

@ chepner 그래서 유효한 솔루션이 아니십니까? 다른 것을 사용해야합니까?
— user2497

6
[ "" = "$var" ]잘 작동합니다. 인용 된 빈 문자열은의 인수 목록에서 제거되지 않습니다 [. 그러나 그것은 [ -z "$var" ] 또한 잘 작동 하기 때문에 필요하지 않습니다 .
— chepner

답변:


37

당신의 라인

[ "${#}" -eq 1 ] || echo "Invalid number of arguments, expected one."; exit 1

이것은

[ "${#}" -eq 1 ] || echo "Invalid number of arguments, expected one."
exit 1

( ;대부분의 경우 인용 부호 를 줄 바꿈 문자로 대체 할 수 있음)

이는 exit 1명령문이 스크립트에 전달 된 인수 수에 관계없이 항상 실행 됨을 의미합니다 . 이는 메시지 The given argument is empty.가 인쇄 될 가능성이 없다는 것을 의미합니다 .

"단락 구문"을 사용하여 테스트 후 둘 이상의 명령문을 실행하려면에서 명령문을 그룹화하십시오 { ...; }. 대안은 적절한 if명령문 을 사용하는 것입니다 (IMHO는 스크립트에서 더 깔끔해 보입니다).

if [ "$#" -ne 1 ]; then
    echo 'Invalid number of arguments, expected one.' >&2
    exit 1
fi

두 번째 테스트와 동일한 문제가 있습니다.


에 관해서

[ -z "" ] && echo A || echo B

이것은 주어진 예제에서 작동하지만 일반

some-test && command1 || command2

할 수 없습니다 와 동일

if some-test; then
    command1
else
    command2
fi

대신에

if ! { some-test && command1; }; then
    command2
fi

또는

if some-test && command1; then
    :
else
    command2
fi

즉, 테스트 또는 첫 번째 명령이 실패하면 두 번째 명령이 실행되므로 관련된 세 개의 명령문을 모두 실행할 수 있습니다.


18

이:

[ "${#}" -eq 1 ] || echo "Invalid number of arguments, expected one."; exit 1

아니다:

[ "${#}" -eq 1 ] || { echo "Invalid number of arguments, expected one."; exit 1; }

그러나 대신 :

{ [ "${#}" -eq 1 ] || echo "Invalid number of arguments, expected one."; } 
exit 1

전달한 인수 수에 관계없이 스크립트가 종료됩니다.


8

가독성을 높이는 한 가지 방법은 다음 과 같은 die함수 (la perl) 를 정의하는 것입니다.

die() {
  printf >&2 '%s\n' "$@"
  exit 1
}

# then:

[ "$#" -eq 1 ] || die "Expected one argument, got $#"

[ -n "$1" ] || die "Empty argument not supported"

필요한 경우 색상, 접두사, 줄 번호와 같은 종과 휘파람을 더 추가 할 수 있습니다.


실제로 die여러 인수를 사용 하여 함수를 호출 한 적이 있습니까? (있는 경우, 예를 들어 줄 수 있습니까?) 나는 거의 동일한 die기능을 사용하지만 "$*"대신에 더 많은 기능을 사용할 수 있습니까?
— jrw32982는 Monica

3
의 값이 "$@"되어 그 개행 문자를 추가 할 필요없이 다중 광고 메시지를 허용.
— Charles Duffy

1
@ jrw32982, "$*"공백을 사용하여 arg 를 결합 하는 데 사용 하면 수정 된 $IFS컨텍스트를 포함한 모든 컨텍스트에서 작동하도록 SPC 로 설정해야합니다 $IFS. 다른 방법으로 ksh/ zsh, 당신이 사용할 수있는 print -r -- "$@"또는 echo -E - "$@"에서 zsh.
— Stéphane Chazelas

@CharlesDuffy 네, 그러나 -type 함수 의 컨텍스트에서 수행 된 것을 본 적이 없습니다die . 내가 묻는 것은 실제로 die "unable to blah:" "some error"2 줄 오류 메시지를 받기 위해 누군가가 글을 쓰는 것을 본 적이 있습니까?
— jrw32982는 Monica를 지원합니다. April

@ StéphaneChazelas 좋은 지적입니다. 따라서 (내 공식에서)이어야합니다 die() { IFS=" "; printf >&2 "%s\n" "$*"; exit 1; }. 여러 종류의 인수를 전달하여 여러 줄 오류 메시지를 생성 die하기 위해 이러한 종류의 함수를 개인적으로 사용한 적이 printf있습니까? 아니면 단일 인수 만 전달하여 die출력에 단일 개행 만 추가합니까?
— jrw32982는 Monica

-1

나는 종종 이것을 빈 문자열에 대한 테스트로 보았다.

if [ "x$foo" = "x" ]; then ...

"="수정되었습니다.
— wef

3
그 관습은 말 그대로 1970 년대에 나온 것입니다. 사용하고, 지금은 쓸모 기능과 같은 인용 알맞은 너무 오래 (1992 POSIX 쉬 표준을 준수하는 쉘을 사용하는 어떠한 이유도 없다 -a, -o, (와 )같은 derectives이 말해 test하나의 호출에 여러 작업을 결합 할 수는 피하십시오; pubs.opengroup.org/onlinepubs/9699919799/utilities/test.html 의 OB 마커를 참조하십시오 .
— Charles Duffy

리눅스가 아닌 유니스는 원래 'sh'를 '90'에 잘 넣었습니다. 당시 필자는 휴대용 설치 스크립트를 작성해야했으며이 구성을 사용했습니다. NVidia에서 Linux로 제공하는 설치 스크립트를 보았지만 여전히이 구성을 사용합니다.
— wef

NVidia가이를 사용할 수는 있지만 기술적으로 정당하다고 말할 수는 없습니다. 상용 유닉스에서의화물 숭배 개발은 슬프게도 널리 퍼져 있습니다. Heirloom Bourne 조차도 문제의 버그가 없으므로 POSIX 이외의 제품을 출시 한 마지막 상용 UNIX 인 SunOS 코드베이스 /bin/sh와 Heirloom Bourne의 직계 전임자 에게는 버그 가 없었습니다.
— Charles Duffy

1
모자를 쓰지 않아서 1990 년 이후이 버그로 상업용 유닉스에 게시 된 셸을 켜야하는 유튜브 비디오를 게시하겠다고 약속 할 수는 없습니다. . :)
— Charles Duffy
당사 사이트를 사용함과 동시에 당사의 쿠키 정책과 개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.