동일하지 않은 구문이 중요합니까?


22

스크립팅 할 때 다음 구문이 사실이 아니라는 것을 이해하기 쉽기 때문에 보통 다음 구문으로 if를 작성합니다.

if [ ! "$1" = "$2" ]; then

다른 사람들은 아래 방법이 더 좋다고 말합니다

if [ "$1" != "$2" ]; then

문제가있는 이유와 차이점이 있는지 아무도 묻지 않는 것입니다.

그렇다면 두 구문 사이에 차이점이 있습니까? 그들 중 하나가 다른 것보다 안전합니까? 아니면 선호 / 습관의 문제입니까?


9
첫 번째 경우는 사업자 구분하기 위해 우선 순위를 알 필요가 !(x==y)에서를 (!x)==y.
jimmij

@jimmij 당신은 문자열을 비교할 때이 있음을 의미합니까 if [ ! "$string" = "one" ]아닌 경우 값으로 변환 $string같음 one. 그리고 이것은 if [ "$string" != "one"]값이 ? $string와 같지 않은 경우로 변환됩니다 one.
Jimmy_A

5
@Jimmy_A 나는 이것이 어떻게 "번역"하는지 알아야한다는 것을 의미한다. 연산자를 모으는 것 ( !=구문)이 더 분명합니다.
jimmij

친애하는 유권자 여러분, Stéphane의 답변에 따르면 행동에 중대한 차이가 있으며 정답은 어떤 식 으로든 의견에 근거하지 않습니다.
Kevin

답변:


35

미용 적 / 선호 적 주장 외에도, 한 가지 이유는 [ ! "$a" = "$b" ]with보다 코너 사례 에서 실패한 구현이 더 많기 때문일 수 있습니다 [ "$a" != "$b" ].

구현 이 POSIX 알고리즘을 따르는 경우 두 경우 모두 안전해야 하지만 오늘날 (작성 초기 2018 년)에도 여전히 실패한 구현이 있습니다. 예를 들어,에 a='(' b=')':

$ (a='(' b=')'; busybox test "$a" != "$b"; echo "$?")
0
$ (a='(' b=')'; busybox test ! "$a" = "$b"; echo "$?")
1

dash같이 발견 된 0.5.8과 같은 이전 버전은 0.5.9로, sh예를 들어 우분투 16.04에 :

$ a='(' b=')' dash -c '[ "$a" != "$b" ]; echo "$?"'
0
$ a='(' b=')' dash -c '[ ! "$a" = "$b" ]; echo "$?"'
1

(0.5.9로 수정, https://www.mail-archive.com/dash@vger.kernel.org/msg00911.html 참조 )

이러한 구현 예는 치료 [ ! "(" = ")" ]로서 [ ! "(" "text" ")" ][ ! "text" ]POSIX 위임 그것이 될 때 ( "텍스트가"널 문자열인지 시험) [ ! "x" = "y" ](시험 "X"와 같은지 "Y"). 이 경우 구현이 잘못된 테스트를 수행하기 때문에 실패합니다.

또 다른 형식이 있습니다.

! [ "$a" = "$b" ]

POSIX 쉘이 필요합니다 (이전 Bourne 쉘에서는 작동하지 않습니다).

참고 여러 구현에 문제가 있었다 [ "$a" = "$b" ](그리고 [ "$a" != "$b" ]뿐만 아니라)를 아직도 좋아한다 [의 내장 /bin/sh솔라리스 10의 (a Bourne 쉘의 POSIX 쉘에있는 /usr/xpg4/bin/sh). 그래서 다음과 같은 것을 보게됩니다.

[ "x$a" != "x$b" ]

오래된 시스템으로 이식 할 수있는 스크립트


다시 말해, 두 구문은 모두 동일하지만 차이가 없지만 ! "$a" = "b"비교를 지정하기 위해 구문 을 작성하는 방법에 대해 더주의를 기울여야합니다. 귀하의 예에서 나는 두 번째 명령이 not zero유익하거나 문제가 될 수 있음을 반환한다는 것을 이해합니다 . 일치하지 않는 경우 종료하고 싶거나 비교가 충돌하는지 확인하려는 경우 문제가 될 수 있습니다.
Jimmy_A

2
@Jimmy_A은, 아니, 그 구현에 [ ! "$a" = "$b" ]바로 그 때 실패 $a입니다 ($b입니다 ), 그것은 그들이 없을 때 그들이 동일한 주장 (과 같은 문자열이 아닌 ),하지만 [그 경우 잘못된 테스트를 수행합니다.
Stéphane Chazelas

아, 알았어요 첫 번째와 세 번째는 조건이 참인지 확인하고 두 번째와 네 번째는 조건이 거짓이면 확인합니다. 따라서 종료 상태 코드가 다릅니다. 기본적으로 1 & 4 변수는 다르고 2 & 3은 같지 않습니다.
Jimmy_A

3
@Jimmy_A, 아니오. 당신은 요점을 완전히 놓쳤다. 경우 이러한 구현은 POSIX 따라, 다음 의 모든 상태 코드는 0이 될 것이다
와일드 카드

내가 이해하게하기 위해, 이것은 다음과 같이 요약됩니다 : [ ! "$a" = "$b" ]버그가있는 쉘 구현에서 때로는 잘못 처리됩니다 (답의 첫 번째 문장을 다소 바꾸고 있다고 생각합니다).
Michael Burr

8

x != y구문 때문에 더 나은 ! x == y오류 경향이있다 - 다르다 언어와 언어의 연산자 우선 순위에 대한 지식이 필요합니다. 구문 은 vs의 우선 순위에 따라 또는 ! x == y로 해석 될 수 있습니다 .!(x == y)(!x) == y!=


예를 들어, c++부정 ! 에서 비교 / 관계 연산자 앞에 오기 == 때문에 다음 코드는 다음과 같습니다.

#include<iostream>

using namespace std;

int main()
{
  int x=1, y=2;
  if(     x  != y   ) cout<<"true"<<endl; else cout<<"false"<<endl;
  if(  !  x  == y   ) cout<<"true"<<endl; else cout<<"false"<<endl;
  if(  !( x  == y ) ) cout<<"true"<<endl; else cout<<"false"<<endl;
  if(   (!x) == y   ) cout<<"true"<<endl; else cout<<"false"<<endl;
}

보고

true
false
true
false

awk유닉스 세계에서 자주 사용되는 도구를 포함하여 다른 많은 언어에서도 비슷한 동작이 관찰 될 수 있습니다 .


반면, 운영자를 통해 모아 x != y도 잘 확립 된 패턴으로 혼동되지 않습니다. 또한 기술적으로 말하면 !=종종 두 개가 아니라 하나의 연산자이므로 별도의 비교와 부정보다 평가하기가 훨씬 빠릅니다. 따라서 두 구문 모두 bash에서 작동하지만 x != y표준 논리를 따르는 코드를 읽고 유지 관리하는 것이 더 쉽기 때문에 따르는 것이 좋습니다 .


4

"답변"은 개인의 두뇌가 연결되는 방식에 크게 의존하기 때문에 이런 종류의 것은 매우 의견에 기반합니다. 의미 적으로는와 NOT ( A == B )동일하지만 (A != B ), 한 사람이 다른 사람에게 더 명확 할 수 있습니다. 또한 상황에 따라 다릅니다. 예를 들어, 플래그가 설정되어 있으면 한 구문이 다른 구문보다 의미가 더 명확 할 수 있습니다.

if NOT ( fileHandleStatus == FS_OPEN )

반대로

if ( fileHandleStatus != FS_OPEN )

그리고 전자가 배정되고 나중에 평등 테스트 (C와 같은) 인 언어 대신 if ( FS_OPEN != fileHandleStatus )실수로 타이핑하기 쉬워 진 결과 에도===
derobert
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.