[[$ a == z *]]와 [$ a == z *]의 차이점은 무엇입니까?


35

이 둘 사이에 어떤 차이가 있습니까?

[[ $a == z* ]]

[ $a == z* ] 

서로 다른 출력을 갖는 예제를 가질 수 있습니까?

또한 작동 방식은 어떻게 [[ ]]다른 [ ]가요?

답변:


41

의 차이 [[ … ]]와는 [ … ]주로 덮여있다 배쉬 - 단일 또는 이중 브라켓을 사용 . 결정적으로, [[ … ]]특별한 문법이지만 [, 명령에 대한 재미있는 이름입니다. [[ … ]]내부에 대한 특별한 구문 규칙이 [ … ]있습니다.

와일드 카드 주름이 추가되면 다음과 같이 [[ $a == z* ]]평가됩니다.

  1. 명령을 구문 분석하십시오. 이것은 [[ … ]]조건식 주위의 조건부 구문 $a == z*입니다.
  2. 조건식을 구문 분석하십시오. 이것은 ==피연산자 $a와 및를 가진 2 진 연산자 z*입니다.
  3. 첫 번째 피연산자를 변수 값으로 확장하십시오 a.
  4. ==연산자를 평가하십시오 . 변수 값이 apattern과 일치 하는지 테스트하십시오 z*.
  5. 조건식을 평가하십시오. 결과는 조건부 연산자의 결과입니다.
  6. 이제 명령이 평가되며 조건식이 true이면 상태가 0이고 false이면 1입니다.

[ $a == z* ]평가 방법 은 다음과 같습니다 .

  1. 명령을 구문 분석 : 이것은이다 [단어를 평가에 의해 형성되는 인수 명령 $a, ==, z*, ].
  2. $a변수 값으로 확장하십시오 a.
  3. 명령 매개 변수에서 단어 분리 및 파일 이름 생성을 수행하십시오.
    • 예를 들어,의 값이있는 경우 a의 6 문자 스트링 foo b*(예에 의해 수득 a='foo b*') 및 (상기 현재 디렉토리의 파일 목록 bar, baz, qux, zim, zum), 그 팽창의 결과는 단어의 다음 목록은이 : [, foo, bar, baz, ==, zim, zum, ].
  4. [이전 단계에서 얻은 매개 변수로 명령 을 실행하십시오 .
    • 위의 예제 값으로 [명령은 구문 오류를 불평하고 상태 2를 리턴합니다.

참고 : [[ $a == z* ]]3 단계에서의 값은 a단일 단어가 예상되는 상황 (조건부 연산자의 왼쪽 인수)이므로 단어 분할 및 파일 이름 생성을 거치지 않습니다 ==. 대부분의 경우 단일 단어가 해당 위치에서 의미가있는 경우 변수 확장은 큰 따옴표처럼 작동합니다. 그러나 해당 규칙에는 예외가 있습니다. in [[ abc == $a ]]의 값에 a와일드 카드 가 포함 된 a경우 와일드 카드 패턴과 일치합니다. 의 값이 예를 들어, aa*다음 [[ abc == $a ]]사실이다 (와일드 카드 때문에 *의 인용 부호가 확장에서 오는 $a일치 *) 반면 [[ abc == "$a" ]](거짓 일반 문자 때문에*의 인용 된 확장에서 온 $a것이 일치하지 않습니다 bc). 내부는 [[ … ]]큰 따옴표는, 변화를하지 않는 문자열 일치 연산자의 오른쪽에 제외 ( =, ==, !==~).


39

[test명령 의 별명입니다 . 유닉스 버전 6에는 if명령이 있었지만, 버전 7 (1979) 에는 if-then-else-elif-fi 구문을 포함하여 몇 가지 프로그래밍 구문이 포함 된 새로운 Bourne 쉘 이 제공 되었으며 Unix 버전 7 은 대부분의 명령을 추가했습니다 . 이전 버전 의 명령 으로 수행 된 "테스트" .testif

[은 별칭으로 test만들어졌으며 둘 다 Unix System III (1981)의 쉘에 내장되었습니다 . 비록 일부 유닉스 변종은 [그 이후 로 명령 이 없었 습니다sh ( 2000 년 초까지 Almquist 쉘을 기반으로하는 일부 BSD에서 ( 기본적으로test 항상 ash소스 에 포함되어 있지만 BSD는 처음에 비활성화되었습니다)).

참고 test일명 ["테스트"를 수행하는 명령이다는 항등 연산자는 그래서 그래서, 과제와 평등 운영자들 사이를 명확하게 할 이유가 없다, 그 명령을 수행한다는 과제가 없습니다 =. ==은 최근의 일부 구현에서만 지원되며 [의 별칭 일뿐 =입니다.

때문에 [아무것도 더 많은 명령 이상을하지 않습니다, 그것은 쉘에 의해 다른 명령과 동일한 방식으로 구문 분석됩니다.

구체적으로, 귀하의 예에서 $a인용되지 않았기 때문에 일반적인 단어 분리 규칙에 따라 여러 단어로 나뉘어지며 각 단어는 파일 이름 생성을 일으켜 더 많은 단어로 이어질 수 있습니다. [명령에 대한 별도의 인수 .

마찬가지로으로 z*시작하는 현재 디렉토리의 파일 이름 목록으로 확장됩니다 z.

경우에 따라서 예를 들어, $a이다 b* = x,하고있다 z1, z2, b1그리고 b2현재 디렉토리에있는 파일의 [명령 (9 개) 인수를 얻을 것입니다 : [, b1, b2, =, x, ==, z1, z2].

[인수를 조건식으로 구문 분석합니다. 이 9 개의 인수는 유효한 조건식에 합산되지 않으므로 아마도 오류를 반환 할 것입니다.

[[ ... ]]구조는 ksh86a1987 년에 Korn 쉘에 의해 도입되었는데, 1987 년 ksh88에는 처음부터 가지고 있었지만 없었습니다.

ksh (모든 구현) 외에도 [[...]]bash (버전 2.02부터)와 zsh에서도 지원되지만, 세 가지 구현은 서로 다르며 변경 사항은 일반적으로 이전 버전과 호환 가능하지만 동일한 쉘의 각 버전마다 차이가 있습니다 (bash의 예외는 주목할만한 예외입니다) =~동작이 변경 될 때 특정 버전 후에 몇 개의 스크립트를 중단하는 것으로 알려진 연산자). [[...]]POSIX 또는 Unix 또는 Linux (LSB)에 의해 지정되지 않았습니다. 포함을 몇 번 포함하는 것으로 간주되었지만 주요 쉘에서 지원하는 공통 기능으로 이미 [명령 및 case-in-esac구성에 포함되어 있기 때문에 포함되지 않았습니다 .

전체 [[ ... ]]구조는 명령을 구성합니다. 즉, 종료 상태 (조건부 표현식을 평가 한 결과 가장 중요한 자산 임)가 있으며 다른 명령으로 파이프 할 수 있으며 (유용하지는 않지만) 일반적으로 원하는 위치에 사용할 수 있습니다. 쉘 명령이므로 쉘 내에서만 다른 명령을 사용하지만 일반적인 간단한 명령처럼 구문 분석되지 않습니다. 내부는 조건식으로 쉘에 의해 구문 분석 되며 일반적인 단어 분할 및 파일 이름 생성 규칙이 다르게 적용됩니다.

[[ ... ]]==처음부터 알고 있으며 =1 과 같습니다 . ksh의 혼란은 (그리고 혼란과 많은 버그를 유발하고 있습니다) =and ==는 등호 연산자가 아니라 패턴 일치 연산자입니다 (하지만 일치하는 측면은 인용 부호로 비활성화 할 수 있지만 쉘마다 다른 명확한 규칙으로 비활성화 할 수는 있음).

위의 코드 [[ $a == z* ]]에서 쉘은 일반적인 토큰과 비슷한 규칙으로 여러 토큰으로 구문 분석하고 패턴 일치 비교로 인식 z*하며 a변수 의 내용과 일치하는 패턴으로 처리 합니다.

일반적으로 명령 [[ ... ]]보다 발로 자신을 쏘기가 더 어렵습니다 [. 그러나 같은 몇 가지 규칙

  • 항상 변수를 인용
  • -aor -o연산자를 사용하지 마십시오 (여러 [명령 &&|| 연산자 사용)

확인 [POSIX 쉘과 신뢰성.

[[...]]다른 쉘 -nt에서는 정규 표현식 일치 연산자와 같은 추가 연산자를 지원 하지만 목록과 동작은 쉘마다, 버전마다 다릅니다.

따라서 스크립트가 해석 할 쉘 및 최소 버전을 모른다면 표준 [명령 을 사용하는 것이 더 안전 할 것입니다 .


1 예외 : [[...]]version의 bash에 추가되었습니다 2.02. 2.03변경이 [[ x = '?' ]]있을 때까지 true를 [[ x == '?' ]]반환하고 false를 반환합니다 . 즉, 인용은 =해당 버전 에서 연산자를 사용할 때 패턴 일치를 방해하지 않지만를 사용할 때 따옴표로 묶었습니다 ==.


훌륭한 정보. "-a 또는 -o 연산자를 사용하지 않는"이유를 설명해 주시겠습니까?
grebneke

@grebneke 시도 [ '!' = foo -o a = a ]에서 bash예를 들어.
Stéphane Chazelas

0

둘 다 표현식을 평가하는 데 사용되며 [[POSIX 이전 버전의 쉘에서는 작동하지 않으며 패턴 일치 및 정규식도 지원합니다. 예를 들어보십시오

[ $n -eq 0 -a $y -eq 0 ] && echo "Error" || echo "Ok"

[[ $n -eq 0 && $y -eq 0 ]] && echo "Error" || echo "Ok"


Bourne 쉘은 POSIX가 아니며 [[...]]일부 버전의 [정규 표현식 일치 와 마찬가지로 일부 쉘의 일부 버전에서만 정규 표현식을 지원합니다. 수학적 비교를 위해을 지원하는 쉘 [[에서 다음과 같이 작성하십시오(( n == 0 && y == 0))
Stéphane Chazelas
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.