쉘 논리 부정

쉘 논리 부정

둘 중에 뭘 더 좋아하시나요?

if ! [ ... ]; then

그리고

if [ ! ... ]; then

실제로 결과는 동일합니다. 선호하는 구문이 있습니까? 전자의 구문에서는 not이 쉘 내장으로 평가되는 반면, 후자의 구문에서는 not이 내장으로 평가됩니다 test.

답변1

이식성 고려 사항.

키워드는 POSIX이지만 Bourne은 아니며 / 명령은 !처음부터 !지원됩니다 .[test

그래서 .[ ! ... ]! [ ... ]

-o그렇지 않으면 더 이상 사용되지 않는 연산자 와 이항 연산자를 사용하지 않는 한 동일해야 합니다( 구현 시 오래된 / 파싱 버그를 -a제쳐두는 경우 ).test[

실제로 Bourne 쉘에서는 다음을 수행합니다.

if ! cmd1; then
  cmd2
fi

당신은 이것을 해야 합니다:

if cmd1; then
  :
else
  cmd2
fi

(또는 를 사용하십시오 cmd1 || cmd2. 그러나 궁극적으로 종료 상태가 달라질 수 있습니다).

set -o errexit// set -e트랩과 상호작용ERR

iffi@mosvy가 지적했듯이 / 문의 조건부 부분 외에 [ ! ... ]와 사이의 또 다른 차이점은 후자가 ! [ ... ]false를 반환하고 옵션이 켜져 있을 때 쉘이 종료되지 않는다는 것입니다.! [ ... ]errexit

!errexit파이프에 적용하면 쉘이 파이프의 종료 상태를 다음과 같이 간주하므로 효과가 취소됩니다.상황. failing-pipeline || cmd에도 동일하게 적용되거나 failing-pipeline && cmd...

그리고 는 [ ! ... ]명령 !에 전달되는 일반 매개변수일 뿐입니다 [. 궁극적으로 셸에 관한 한 이는 성공 또는 실패 종료 상태를 반환하는 명령 errexit일 뿐입니다 .[

$ sh -ec '[ ! a = a ]; echo here'; echo "$?"
1
$ sh -ec '! [ a = a ]; echo here'; echo "$?"
here
0

if이는 에 표시된 대로 while// 문의 조건부 부분으로 이러한 명령이 실행되는 경우에는 적용 되지 않습니다.untilerrexit

ERRKorn의 포탄과 같은 함정 에도 동일하게 적용됩니다 .

$ ksh -c 'trap "echo OUCH" ERR; ! [ a = a ]'
$ ksh -c 'trap "echo OUCH" ERR; [ ! a = a ]'
OUCH

실제로 이는 [거의 항상 조건으로 사용되며 적용되지 않는 경우( // 문 또는 뒤에 / 가 오는 경우 ) 에 errexit적용되지 않기 때문에 아마도 차이가 없을 것입니다.ifwhileuntil&&||

답변2

[ … ]같음 test …, 그래서 ! [ … ]같음 ! test …. 이는 명령의 결과를 부정한다는 의미입니다 test. 이 경우에는 !쉘 명령입니다.

info bash예를 들어 "파이프라인" 섹션에서 다음을 수행 합니다 .

예약어 '!'가 파이프 앞에 오면 종료 상태는 위의 종료 상태에 대한 논리적 부정입니다.

반면에 는 [ ! … ]을 의미합니다 test ! …. 이는 테스트에서 표현식을 부정한다는 의미입니다. 또한보십시오 !:man test

   ! EXPRESSION
          EXPRESSION is false

그래서 다른 의미를 가질 수 있습니다. 복잡한 표현식이 있는 경우 부정은 표현식의 일부에만 작동할 수 있습니다.

당신이 좋아하는 것은 당신에게 달려 있습니다.

관련 정보