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


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.