`[`는 쉘 내장 함수이고 `[[`는 쉘 키워드인 이유는 무엇입니까?

`[`는 쉘 내장 함수이고 `[[`는 쉘 키워드인 이유는 무엇입니까?

제가 아는 한에는 [[그렇습니다. 강화된 버전 [인데, [[키워드 로 보고 내장으로 나오니 [헷갈리네요 .

[root@server ~]# type [
[ is a shell builtin
[root@server ~]# type [[
[[ is a shell keyword

TLDP설명하다

내장 명령은 동일한 이름의 시스템 명령과 동의어일 수 있지만 Bash는 이를 내부적으로 다시 구현합니다. 예를 들어, Bash echo 명령은 /bin/echo와 다르지만 동작은 거의 동일합니다.

그리고

키워드는 예약어, 태그 또는 연산자입니다. 키워드는 셸에 특별한 의미를 가지며 실제로 셸 구문의 구성 요소입니다. 예를 들어 for, while, do 및 !가 키워드입니다. 내장 함수와 마찬가지로 키워드는 Bash에 하드 코딩되어 있지만 내장 함수와는 달리 키워드는 명령 자체가 아니라 명령 구성의 하위 단위입니다. [2]

[이건 make 와 [[키워드로 해야 하지 않나요 ? 여기서 뭔가 빠졌나요? 반품,이 링크다시 확인하시면 [동일한 [[카테고리에 속해 있을 것입니다.

답변1

[와 의 차이점은 [[매우 근본적입니다.

  • [명령이다. 해당 인수는 다른 명령 인수와 동일하게 처리됩니다. 예를 들어 다음을 고려하십시오.

    [ -z $name ]
    

    쉘이 확장되어 $name실행됩니다.둘 다결과는 다른 명령과 마찬가지로 토큰화되고 파일 이름이 생성됩니다.

    예를 들어 다음 작업은 실패합니다.

    $ name="here and there"
    $ [ -n $name ] && echo not empty
    bash: [: too many arguments
    

    이것이 제대로 작동하려면 따옴표가 필요합니다.

    $ [ -n "$name" ] && echo not empty
    not empty
    
  • [[특수 규칙에 따라 인수가 처리되는 쉘 키워드입니다. 예를 들어 다음을 고려하십시오.

    [[ -z $name ]]
    

    쉘은 확장되지만 $name다른 명령과 달리 실행됩니다.어느 것도 아니다결과에 대해 단어 분할 또는 파일 이름 생성을 수행합니다. 예를 들어, 다음은 공백이 포함되어 있어도 성공합니다 name.

    $ name="here and there"
    $ [[ -n $name ]] && echo not empty
    not empty
    

일반화하다

[셸에서 실행되는 다른 모든 명령과 동일한 규칙을 따르는 명령입니다.

그러나 [[명령이 아닌 키워드이기 때문에 쉘에서 특별히 다루어지며 매우 다른 규칙에 따라 작동합니다.

답변2

존재하다V7 유닉스— Bourne 쉘이 처음 등장한 곳 — 은 [으로 test만 시작되었습니다 /bin/test. 따라서 오늘 작성할 코드는 다음과 같습니다.

if [ "$foo" = "bar" ] ; then ...

당신은 쓸 것입니다

if test "$foo" = "bar" ; then ...

두 번째 표기법은 여전히 ​​존재하며 이것이 무슨 일이 일어나고 있는지 더 명확하게 해줍니다. test인수를 평가하고 다음을 반환하는 명령을 호출하고 있습니다.종료 상태 코드if다음에 무엇을 할지 결정하는 데 사용됩니다 . 명령은 셸에 내장되어 있을 수도 있고 외부 프로그램일 수도 있습니다.

[나중에 교체로 test. ² 의 내장 동의어일 수도 있지만 내장되지 않은 쉘의 최신 시스템에서도 제공됩니다 test./bin/[

[그리고 test동일한 코드를 사용하여 달성할 수 있습니다. 이것은 OS X /bin/[의 경우입니다 /bin/test.하드 링크동일한 실행 파일에. 따라서 구현은 후행을 완전히 무시합니다 ]. as로 호출하면 필요하지 않고 /bin/[, as로 호출하면 필요하지 않습니다.하다제공됩니다 /bin/test.⁴

[[이라는 이름의 원래 프로그램이 없었기 때문에 이 기록 중 어느 것도 아무런 차이를 만들지 않습니다 [[. 확장으로 구현하는 쉘에만 존재합니다.POSIX 쉘.

"내장"과 "키워드"의 차이점 중 일부는 이러한 역사 때문입니다. 이는 또한 [[다음에서 지적한 것처럼 표현식을 구문 분석하기 위한 구문 규칙이 다르다는 사실을 반영합니다.John1024의 답변.⁵


각주:

  1. 이렇게 보면 [대부분의 다른 프로그래밍 언어에서 괄호와 대괄호가 작동하는 방식과 달리 쉘 스크립트에 공백을 추가해야 하는 이유가 분명해집니다. 쉘의 명령 구문 분석기가 이를 허용하는 경우 if["$x"..., 또한 허용해야 합니다.iftest"$x"...

  2. 1980년쯤에 일어난 일이다. /bin/[내 사본에는 존재하지 않습니다고대 유닉스 V7또한 1979년 이후에는 man test별칭으로 기록되지 않았습니다 . 해당 매뉴얼 페이지 항목에 시험판 버전이 있습니다.시스템 31980년 매뉴얼,목록.

  3. ls -i /bin/[ /bin/test

  4. 하지만 이런 행동은 기대하지 마세요. Bash 내장 버전은 [꺼야 하며 ], 그렇게 하면 내장 test구현이 불만을 표시합니다.하다제공하세요.

  5. 내장 명령과 외부 명령 간의 구별은 또 다른 이유로 중요할 수도 있습니다. 두 구현의 동작이 다를 수 있습니다. echo이는 많은 시스템의 경우입니다. 구현이 하나만 있으므로 키워드를 구분할 필요가 없습니다.

답변3

[원래는 외부 명령이었지만 /bin/test일부 명령(예: [echo)은 쉘 스크립트에서 너무 자주 사용되었기 때문에 쉘 구현자는 사용될 때마다 다른 명령을 실행하지 않고 코드를 쉘 자체에 직접 복사하기로 결정했습니다. 프로세스. 이렇게 하면 이러한 명령이 "내장 명령"으로 바뀌지만 전체 경로로 외부 프로그램을 계속 호출할 수 있습니다.

[[매우 늦게 왔습니다. 내장 명령은 셸 내부에서 구현되지만 외부 명령과 동일한 방식으로 구문 분석됩니다. John1024의 답변에서 설명했듯이 이는 인용되지 않은 변수가 토큰을 토큰화하고 및 >같은 토큰이 <I/O 리디렉션으로 처리됨을 의미합니다. 이로 인해 복잡한 비교 표현식을 작성하는 것이 불편해집니다. [[특별히 구문 분석할 수 있도록 쉘 구문으로 생성됩니다. 변수는 내부적으로 [[토큰화되지 않으며 비교 연산자로 사용될 수 있으며 <다음 인수가 인용되는지 여부 등에 따라 다르게 동작합니다. 이는 기존 명령/내장 명령보다 사용하기 쉬운 편의성입니다.>=[[[

[수백만 개의 스크립트에 대해 호환되지 않는 변경이 될 수 있는 구문으로 간단히 다시 코딩할 수는 없습니다 . 이전에 존재하지 않았던 새로운 구문을 사용함으로써 [[상위 호환 방식으로 사용 방식을 완전히 변경할 수 있습니다.

$((...))이는 본질적으로 전통적인 명령을 대체한 산술 표현식 구문의 진화 와 유사합니다 expr.

답변4

최신 은[[bash최적화[.

고전적인 [방법은 사소한 작업을 수행하는 데 자주 사용된다는 점에서 큰 단점이 있습니다. 매번 새로운 프로세스를 생성합니다. ( 매번 합계를
비교하기 위해 새로운 주소 공간을 생성합니다 !)01

추가해야 할 중요한 점 중 하나 [[는 내부 표현의 평가가 [추가 패스를 생성하지 않도록 하는 것입니다. 하지만 [일이 진행되는 방식은 바뀔 수 없습니다. 이로 인해 많은 혼란과 문제가 발생합니다. 따라서 최적화는 새롭고 더 효율적인 이름인 쉘 내장으로 구현됩니다.
부작용으로 쉘 구문의 키워드가 됩니다.

당시 [가장 먼저 사용된 것은,이것이 올바른 방법이다이를 수행하려면 외부 프로세스를 사용하십시오.

관련 정보