배쉬 평등 연산자 (==, -eq)


136

누군가 가 bash 스크립팅 -eq과 의 차이점을 설명해 주 ==시겠습니까?

다음과 같은 차이점이 있습니까?

[ $a -eq $b ][ $a == $b ]

그것은 단순히 즉 ==변수가 숫자가 포함되어있는 경우에만 사용됩니다?

답변:


187

그것은 다른 방법으로 주위의 : ===문자열 비교위한, -eq숫자들입니다. -eq같은 가족이다 -lt, -le, -gt, -ge,와 -ne, 그건 당신이 어떤을 어떤 기억하는 데 도움합니다.

==그건 그렇고 배쉬 즘입니다. POSIX를 사용하는 것이 좋습니다 =. bash에서 두 가지는 동일하며 보통 sh =만이 작동하도록 보장됩니다.

$ a=foo
$ [ "$a" = foo ]; echo "$?"       # POSIX sh
0
$ [ "$a" == foo ]; echo "$?"      # bash specific
0
$ [ "$a" -eq foo ]; echo "$?"     # wrong
-bash: [: foo: integer expression expected
2

(Side note : 변수 확장을 인용하십시오! 위의 큰 따옴표를 생략하지 마십시오.)

#!/bin/bash스크립트를 작성하는 경우 대신을 사용 [[하는 것이 좋습니다 . 두 배로 된 양식에는 더 많은 기능, 더 자연스러운 구문 및 더 적은 문제가 있습니다. 큰 따옴표는 더 이상 필요하지 않습니다 $a.

$ [[ $a == foo ]]; echo "$?"      # bash specific
0

또한보십시오:


1
@DJCrashdummy [[는 전체적으로 bash (및 다른 많은 쉘)가 채택한 1980 년대 ksh-ism입니다. 그게 요점입니다-당신이 [[ 전혀 가지고 있다면, 당신은 ksh가 그 주위에 구현 한 모든 확장 ( fnmatch()-스타일 패턴 일치, ERE 정규 표현식 =~, 및 문자열 분할 및 파일 시스템 글 로빙 억제)을 안전하게 가정 할 수 있습니다 유효한. 때문에 [[전체 비 POSIX 구문은, 그것으로 태어난 기능을 사용할 수 있습니다 가정에서 추가적인 휴대 손실은 없습니다.
Charles Duffy

1
@DJCrashdummy는 ... 링크가 따옴표는 때때로에 필요한 것을 정확하게 점을 보여 오른쪽[[ $var = $pattern ]]당신이 그렇지 않으면 대신 리터럴 문자열로 해석에 fnmatch에서 파생 된 패턴으로 해석 될 것입니다 무엇을 원하는 경우. 이 문자열 foo에는 문자 그대로의 해석이 없으므로 인용 부호를 완전히 안전합니다. OP 가 따옴표 또는 이스케이프가 필요한 foo*문자열 과 일치 할 수있는 것을 의미하지 않고 (문자열로 별표를 사용하여) 일치시키려는 경우에만 foo가능합니다.
Charles Duffy

@CharlesDuffy 불행히도 나는 내 의견이 삭제 된 것으로 보이며 꽤 시간이 지났기 때문에 기억할 수 없기 때문에 무엇을 언급하고 있는지 전혀 모른다. :-(
DJCrashdummy

@DJCrashdummy, ... 어, 당신이 직접 철회했다고 가정합니다. 기본적으로 이것은 [[bashism 내부의 인용되지 않은 확장에 대한 반대 의견 이었습니다 (이것이 당신이 대답을 +1하지 않은 유일한 이유임을 나타냅니다).
Charles Duffy

@CharlesDuffy 아니, 유일한 이유는 아닙니다 : 간단한 작업에 대해 bash-isms, ksh-isms 등을 좋아하지 않는다는 사실 외에도 (어려움을 유발하고 초보자를 혼란스럽게합니다), 나는 왜 단일 혼합을 얻지 못합니다. 중괄호 [ ... ]및 이중 등호 ==. :-/
DJCrashdummy

27

연산자 주위의 테스트 구성 에 따라 다릅니다 . 옵션은 이중 괄호, 이중 괄호, 단일 괄호 또는 테스트입니다.

당신이 사용하는 경우 ((...)) , 당신은 산술 지분을 테스트하는 ==C에서와 같이 :

$ (( 1==1 )); echo $?
0
$ (( 1==2 )); echo $?
1

(참고 : 0수단 true유닉스 감각과 비 제로에 실패한 테스트입니다)

-eq이중 괄호 안에 사용하면 구문 오류가 발생합니다.

당신이 사용하는 경우 [...] (또는 단일 중괄호) 또는 [[...]] (또는 이중 중괄호), 또는 test, 당신은 -eq, -ne, -lt, -le, -gt 중 하나를 사용하거나 산술 비교 로서 -ge .

$ [ 1 -eq 1 ]; echo $?
0
$ [ 1 -eq 2 ]; echo $?
1
$ test 1 -eq 1; echo $?
0

==단일 또는 이중 중괄호 (또는 test명령) 의 내부 는 문자열 비교 연산자 중 하나입니다 .

$ [[ "abc" == "abc" ]]; echo $?
0
$ [[ "abc" == "ABC" ]]; echo $?
1

문자열 연산자 는 공백 또는 필요한 공백과 =같습니다 .=====

당신은 동안 [[ 1 == 1 ]]또는 [[ $(( 1+1 )) == 2 ]]그 문자열 평등 시험하고있다 -하지 산술 평등을.

그래서 -eq결과 생산 아마 의 정수 값 것으로 예상 1+1IS가 동일 2RH 문자열과 뒤에 공간이 비록를 :

$ [[ $(( 1+1 )) -eq  "2 " ]]; echo $?
0

동일한 문자열 비교가 후미 공간을 차지하므로 문자열 비교가 실패합니다.

$ [[ $(( 1+1 )) ==  "2 " ]]; echo $?
1

그리고 잘못된 문자열 비교는 완전한 오답을 만들 수 있습니다. '10'는 사 전적으로 문자열 비교 반환 그래서, 이하 '2'가 아닌 true0. 많은 사람들 이이 버그에 물 렸습니다.

$ [[ 10 < 2 ]]; echo $?
0

(10)에 대한 정확한 검사가되는 대 수학적으로 2 이상의 :

$ [[ 10 -lt 2 ]]; echo $?
1

주석 에서 문자열에 정수 를 사용하는 기술적 이유에 대한 의문 -eq이 있습니다. 동일하지 않은 문자열에 대해서는 True를 반환합니다.

$ [[ "yes" -eq "no" ]]; echo $?
0

그 이유는 Bash가 형식화되지 않았기 때문 입니다. 는 -eq문자열이 정수로 해석됩니다 가능하면 기본 변환을 포함 :

$ [[ "0x10" -eq 16 ]]; echo $?
0
$ [[ "010" -eq 8 ]]; echo $?
0
$ [[ "100" -eq 100 ]]; echo $?
0

그리고 0배쉬는 그냥 문자열입니다 생각하는 경우 :

$ [[ "yes" -eq 0 ]]; echo $?
0
$ [[ "yes" -eq 1 ]]; echo $?
1

그래서 [[ "yes" -eq "no" ]]동일합니다[[ 0 -eq 0 ]]

마지막 참고 사항 : 테스트 구조에 대한 많은 Bash 특정 확장은 POSIX가 아니므로 다른 쉘에서 실패합니다. 다른 쉘은 일반적으로 지원하지 않습니다 [[...]]((...))== .


True 를 반환해야하는 기술적 이유가 궁금합니다 [[ "yes" -eq "no" ]]. bash는 이러한 문자열을 비교할 수있는 정수 값으로 어떻게 강제 변환합니까? ;-)
odony

4
배쉬 변수는 타입지정되지 않았 거나 -모두 참 [[ "yes" -eq "no" ]]과 같습니다 . 힘은 비교 정수. 는 정수로 해석됩니다 ; 다른 정수가이거나 문자열 결과가 인 경우 비교는 True 입니다 . [[ "yes" -eq 0 ]][[ "yes" -eq "any_noninteger_string" ]]-eq"yes"000
dawg

Boo, hiss re : ==코드 샘플에 (휴대 불가능) 표시 하고 =아래에 (휴대 가능, 표준화) 언급 만합니다.
찰스 더피

24

==은 bash 특정 별명이며 =숫자 비교 대신 문자열 (어휘) 비교를 수행합니다. eq물론 숫자 비교입니다.

마지막으로, 나는 일반적으로 양식을 사용하는 것을 선호합니다 if [ "$a" == "$b" ]


15
POSIX ==에서만 =지정한 대로 여기를 사용하는 것은 잘못된 형식 입니다.
Charles Duffy

9
당신이 정말로 사용을한다면 ==다음 사이에 넣어 [[]]. (그리고 스크립트의 첫 줄 /bin/bash
이을

18

Guys : 몇 가지 답변이 위험한 예를 보여줍니다. OP의 예는 [ $a == $b ]특별히 인용되지 않은 변수 대체를 사용했습니다 ('17 년 10 월 편집 기준). 의 경우 [...]해당 문자열 평등 안전합니다.

그러나와 같은 대안을 열거 [[...]]하려면 오른쪽을 인용해야한다는 사실도 알려 주어야합니다. 인용하지 않으면 패턴 일치입니다! (bash 매뉴얼 페이지에서 : "패턴의 어떤 부분이라도 문자열과 일치하도록 인용 될 수있다").

bash에서 "yes"를 생성하는 두 명령문은 패턴 일치이고 다른 세 개는 문자열 동등입니다.

$ rht="A*"
$ lft="AB"
$ [ $lft = $rht ] && echo yes
$ [ $lft == $rht ] && echo yes
$ [[ $lft = $rht ]] && echo yes
yes
$ [[ $lft == $rht ]] && echo yes
yes
$ [[ $lft == "$rht" ]] && echo yes
$

2
요구가되게합니다 [ "$lht" = "$rht" ] 따옴표와 평등에 대한 신뢰성도 할 수 있습니다. 당신이 만든 파일이있는 경우 touch 'Afoo -o AB', [ $lft = $rht ]해당 파일 이름에도 불구하고, true를 돌려줍니다 전혀하지 동일로 AB.
Charles Duffy
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.