제가 아는 한에는 [[
그렇습니다. 강화된 버전 [
인데, [[
키워드 로 보고 내장으로 나오니 [
헷갈리네요 .
[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의 답변.⁵
각주:
이렇게 보면
[
대부분의 다른 프로그래밍 언어에서 괄호와 대괄호가 작동하는 방식과 달리 쉘 스크립트에 공백을 추가해야 하는 이유가 분명해집니다. 쉘의 명령 구문 분석기가 이를 허용하는 경우if["$x"...
, 또한 허용해야 합니다.iftest"$x"...
1980년쯤에 일어난 일이다.
/bin/[
내 사본에는 존재하지 않습니다고대 유닉스 V7또한 1979년 이후에는man test
별칭으로 기록되지 않았습니다 . 해당 매뉴얼 페이지 항목에 시험판 버전이 있습니다.시스템 31980년 매뉴얼,예목록.ls -i /bin/[ /bin/test
하지만 이런 행동은 기대하지 마세요. Bash 내장 버전은
[
꺼야 하며]
, 그렇게 하면 내장test
구현이 불만을 표시합니다.하다제공하세요.내장 명령과 외부 명령 간의 구별은 또 다른 이유로 중요할 수도 있습니다. 두 구현의 동작이 다를 수 있습니다.
echo
이는 많은 시스템의 경우입니다. 구현이 하나만 있으므로 키워드를 구분할 필요가 없습니다.
답변3
[
원래는 외부 명령이었지만 /bin/test
일부 명령(예: [
및 echo
)은 쉘 스크립트에서 너무 자주 사용되었기 때문에 쉘 구현자는 사용될 때마다 다른 명령을 실행하지 않고 코드를 쉘 자체에 직접 복사하기로 결정했습니다. 프로세스. 이렇게 하면 이러한 명령이 "내장 명령"으로 바뀌지만 전체 경로로 외부 프로그램을 계속 호출할 수 있습니다.
[[
매우 늦게 왔습니다. 내장 명령은 셸 내부에서 구현되지만 외부 명령과 동일한 방식으로 구문 분석됩니다. John1024의 답변에서 설명했듯이 이는 인용되지 않은 변수가 토큰을 토큰화하고 및 >
같은 토큰이 <
I/O 리디렉션으로 처리됨을 의미합니다. 이로 인해 복잡한 비교 표현식을 작성하는 것이 불편해집니다. [[
특별히 구문 분석할 수 있도록 쉘 구문으로 생성됩니다. 변수는 내부적으로 [[
토큰화되지 않으며 비교 연산자로 사용될 수 있으며 <
다음 인수가 인용되는지 여부 등에 따라 다르게 동작합니다. 이는 기존 명령/내장 명령보다 사용하기 쉬운 편의성입니다.>
=
[[
[
[
수백만 개의 스크립트에 대해 호환되지 않는 변경이 될 수 있는 구문으로 간단히 다시 코딩할 수는 없습니다 . 이전에 존재하지 않았던 새로운 구문을 사용함으로써 [[
상위 호환 방식으로 사용 방식을 완전히 변경할 수 있습니다.
$((...))
이는 본질적으로 전통적인 명령을 대체한 산술 표현식 구문의 진화 와 유사합니다 expr
.
답변4
최신 은[[
bash
최적화의 [
.
고전적인 [
방법은 사소한 작업을 수행하는 데 자주 사용된다는 점에서 큰 단점이 있습니다. 매번 새로운 프로세스를 생성합니다. ( 매번 합계를
비교하기 위해 새로운 주소 공간을 생성합니다 !)0
1
추가해야 할 중요한 점 중 하나 [[
는 내부 표현의 평가가 [
추가 패스를 생성하지 않도록 하는 것입니다. 하지만 [
일이 진행되는 방식은 바뀔 수 없습니다. 이로 인해 많은 혼란과 문제가 발생합니다. 따라서 최적화는 새롭고 더 효율적인 이름인 쉘 내장으로 구현됩니다.
부작용으로 쉘 구문의 키워드가 됩니다.
당시 [
가장 먼저 사용된 것은,이것이 올바른 방법이다이를 수행하려면 외부 프로세스를 사용하십시오.