문자열 비교에 같지 않은 연산자 사용


117

PHONE_TYPE변수에 유효한 세 가지 값 중 하나가 포함되어 있는지 확인하려고했습니다 .

if [ "$PHONE_TYPE" != "NORTEL" ] || [ "$PHONE_TYPE" != "NEC" ] ||
   [ "$PHONE_TYPE" != "CISCO" ]
then
    echo "Phone type must be nortel,cisco or nec"
    exit
fi

위의 코드는 저에게 효과적이지 않으므로 대신 시도했습니다.

if [ "$PHONE_TYPE" == "NORTEL" ] || [ "$PHONE_TYPE" == "NEC" ] ||
   [ "$PHONE_TYPE" == "CISCO" ]
then
    :        # do nothing
else
    echo "Phone type must be nortel,cisco or nec"
    exit
fi

이 유형의 작업에 더 확실한 방법이 있습니까?

답변:


162

당신이 찾고있는 것 같아요 :

if [ "$PHONE_TYPE" != "NORTEL" ] && [ "$PHONE_TYPE" != "NEC" ] &&
   [ "$PHONE_TYPE" != "CISCO" ]

이러한 동등한 규칙은 De Morgan의 법칙 이며 귀하의 경우 다음과 같은 의미를 갖습니다.

not(A || B || C) => not(A) && not(B) && not (C)

부울 연산자 or 및 and의 변경 사항에 유의하십시오.

당신이하려고하는 동안 :

not(A || B || C) => not(A) || not(B) || not(C)

분명히 작동하지 않습니다.


28

훨씬 짧은 방법은 다음과 같습니다.

if [[ ! $PHONE_TYPE =~ ^(NORTEL|NEC|CISCO)$ ]]; then 
  echo "Phone type must be nortel, cisco or nec."
fi
  • ^ – 줄의 시작 부분에서 시작과 일치
  • $ – 줄의 끝과 일치
  • =~ -Bash의 내장 정규식 비교 연산자

2
나는 그것이해야한다고 생각if [[ ! $PHONE_TYPE =~ ^(NORTEL|NEC|CISCO)$ ]]; then
밀라노 Simek

12

좋은 답변과 귀중한 교훈;) 메모 만 보충하고 싶습니다.

어떤 유형의 테스트를 사용하려면 코드, 구조, 환경 등에 크게 의존해야합니다.

대안은 다음과 같이 스위치 또는 case명령문 을 사용하는 것입니다.

case "$PHONE_TYPE" in
"NORTEL"|"NEC"|"CISCO")
    echo "OK"
    ;;
*)
    echo "Phone type must be nortel,cisco or nec"
    ;;
esac

두 번째로 대문자 변수 이름을 사용하여주의해야합니다. 이것은 시스템에 의해 도입 된 변수들 사이의 충돌을 막기위한 것이며, 거의 항상 모두 대문자입니다. 따라서 $phone_type대신 $PHONE_TYPE.

그 중 하나는 안전하지만, 모든 대문자를 사용하는 습관이 있다면 언젠가 말할 수 IFS="boo"있고 상처를 입은 세계에 있습니다.

또한 어떤 것이 무엇인지 쉽게 파악할 수 있습니다.

아니이 필요 하지만 강력하게 고려할 것입니다.


또한 아마도 기능에 대한 좋은 후보입니다. 이것은 대부분 코드를 읽고 유지 관리하기 쉽게 만듭니다. 예 :

valid_phone_type()
{
    case "$1" in
    "NORTEL"|"NEC")
        return 0;;
    *)
        echo "Model $1 is not supported"
        return 1;;
    esac
}

if ! valid_phone_type "$phone_type"; then
    echo "Bye."
    exit 1
fi

9

OR이 아닌 AND를 사용해야합니다.

if [ "$PHONE_TYPE" != "NORTEL" ] && [ "$PHONE_TYPE" != "NEC" ] && [ "$PHONE_TYPE" != "CISCO" ]
then

또는

if [ "$PHONE_TYPE" != "NORTEL" -a "$PHONE_TYPE" != "NEC" -a "$PHONE_TYPE" != "CISCO" ]
then

1

위의 답변을 수정하려면 (아직 언급 할 수 없으므로) :

PHONE_TYPE="NORTEL"
if [[ $PHONE_TYPE =~ ^(NORTEL|NEC|CISCO|SPACE TEL)$ ]]; then 
  echo "Phone type accepted."
else
  echo "Error! Phone type must be NORTEL, CISCO or NEC."
fi

= ~를 사용하려면 bash 4 이상이 필요합니다
. bash 3에서는 작동하지 않습니다.

bash 4.3.46 (정상 작동) 및 bash 3.1.17 (작동하지 않음)을 사용하여 MS Windows 7에서 테스트했습니다.

= ~의 LHS는 따옴표로 묶어야합니다. 위의 PHONE_TYPE = "SPACE TEL"도 일치합니다.


0

대신 [[

if [[ "$PHONE_TYPE" != "NORTEL" ]] || [[ "$PHONE_TYPE" != "NEC" ]] || 
   [[ "$PHONE_TYPE" != "CISCO" ]]
then
echo "Phone type must be nortel,cisco or nec"
exit 1
fi

2
물론 이것은 잘못된 것입니다. [[vs [는 논리를 끄는 데 도움이되지 않습니다.
ilkkachu

0

@ 0x80 솔루션을 기반으로 한 변형 제안 :

# define phone brand list
phoneBrandList=" NORTEL NEC CISCO" ## separator is space with an extra space in first place

# test if user given phone is contained in the list
if [[ ${phoneBrandList} =~ (^|[[:space:]])"${userPhoneBrand}"($|[[:space:]]) ]]; then
    echo "found it !"
fi
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.