내가 아는 [[
한의 향상된 버전 [
이지만 [[
키워드로 보았을 때 [
내장으로 표시 되면 혼란 스럽습니다 .
[root@server ~]# type [
[ is a shell builtin
[root@server ~]# type [[
[[ is a shell keyword
TLDP 는 말합니다
내장은 동일한 이름의 시스템 명령과 동의어 일 수 있지만 Bash는이를 내부적으로 다시 구현합니다. 예를 들어, Bash echo 명령은 동작이 거의 동일하지만 / bin / echo와 동일하지 않습니다.
과
키워드는 예약어, 토큰 또는 연산자입니다. 키워드는 쉘에 특별한 의미가 있으며 실제로 쉘 구문의 구성 요소입니다. 예를 들어, 동안, 그리고! 키워드입니다. 기본 제공과 유사하게 키워드는 Bash로 하드 코딩되지만 기본 제공과 달리 키워드 자체는 명령이 아니라 명령 구성의 하위 단위입니다. [2]
그것이 키워드 [
와 [[
키워드를 모두 만들어서는 안 됩니까? 내가 여기서 놓친 것이 있습니까? 또한, 이 링크 모두 것을 재 – 긍정 [
하고 [[
동일한 종류에 속하는 것이다.
답변
의 차이 [
와는 [[
아주 기본입니다.
-
[
명령입니다. 인수는 다른 명령 인수가 처리되는 방식으로 처리됩니다. 예를 들어, 다음을 고려하십시오.[ -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
요약
[
명령이며 쉘이 실행하는 다른 모든 명령과 동일한 규칙이 적용됩니다.
[[
그러나 명령은 키워드가 아니기 때문에 쉘은 특수하게 취급하며 매우 다른 규칙에 따라 작동합니다.
답변
Bourne 쉘이 데뷔 한 V7 Unix 에서는 [
이라고 test
하며로만 존재했습니다 /bin/test
. 따라서 오늘 작성하는 코드는 다음과 같습니다.
if [ "$foo" = "bar" ] ; then ...
대신 다음과 같이 작성했을 것입니다.
if test "$foo" = "bar" ; then ...
이 두 번째 표기법은 여전히 존재하며 진행 상황에 대해 더 명확하다는 것을 알았습니다.라는 명령을 호출 test
하여 인수를 평가하고 다음에 수행 할 작업을 결정 하는 데 사용 되는 종료 상태 코드 를 반환합니다 if
. 이 명령은 셸에 내장되어 있거나 외부 프로그램 일 수 있습니다 .¹
[
대안으로하기 test
그것은위한 내장 동의어가 될 수 later.²왔다 test
, 그러나 또한 제공됩니다 /bin/[
내장 명령으로이없는 쉘에 대한 현대적인 시스템.
[
와 test
동일한 코드를 사용하여 구현 될 수있다. 이에 대한 경우 /bin/[
와 /bin/test
다음은 OS X에 하드 링크 결과 같은 executable.³에, 구현은 완전히 후행를 무시 ]
당신이로 호출하는 경우 그것을 필요로하지 않습니다 /bin/[
, 그것은 불평하지 않습니다 당신이 경우 어떻게 그것을 제공 /bin/test
.⁴
[[
라는 원시 프로그램이 없었기 때문에 그 역사에는 영향을 미치지 않습니다 [[
. POSIX 쉘 의 확장으로 구현하는 쉘 내부에 존재합니다 .
“내장”과 “키워드”의 차이점 중 일부는이 기록 때문입니다. 또한 구문 분석에 대한 구문 규칙 사실 반영 [[
에 지적 표현, 다른 John1024의 답변을 .⁵
각주 :
-
이런 식으로 살펴보면
[
괄호와 대괄호가 대부분의 다른 프로그래밍 언어에서 작동하는 방식과 달리 왜 쉘 스크립트 에 공백을 넣어야하는지 분명하게 알 수 있습니다. 쉘의 명령 파서가 허용 된if["$x"...
경우에도 허용해야합니다.iftest"$x"...
-
1980 년경에 일어났습니다. 1979 년
/bin/[
의 고대 유닉스 V7 사본에는 존재하지 않으며man test
이를 별명으로 문서화 하지도 않습니다 . 필자는 1980 년부터 System III 매뉴얼 의 시험판 사본에있는 해당 맨 페이지 항목 에 나열되어 있습니다. -
ls -i /bin/[ /bin/test
-
그러나이 행동에 의존하지 마십시오. 의 강타 내장 된 버전은
[
폐쇄를 필요로하지]
, 그리고 내장 된test
당신이 경우 구현은 불평 할 를 제공합니다. -
내장 된 명령과 외부 명령의 구별 또한 다른 이유로 중요 할 수 있습니다. 두 구현이 다르게 작동 할 수 있습니다. 이것은
echo
많은 시스템에서 그렇습니다. 구현은 하나뿐이므로 키워드를 구분할 필요가 없습니다.
답변
[
원래는 외부 명령으로 다른 이름이었습니다 /bin/test
. 그러나 [
and와 같은 몇 가지 명령 echo
은 쉘 스크립트에서 자주 사용되므로 쉘 구현자는 코드를 사용할 때마다 다른 프로세스를 실행하지 않고 쉘 자체에 직접 코드를 복사하기로 결정했습니다. 전체 경로를 통해 외부 프로그램을 계속 호출 할 수 있지만이 명령은 “내장”으로 바뀌 었습니다.
[[
훨씬 나중에왔다. 내장은 셸 내에서 내부적으로 구현되지만 외부 명령과 마찬가지로 구문 분석됩니다. John1024의 답변에서 설명했듯이 인용되지 않은 변수는 단어 분할을 수행하고 토큰 은 I / O 리디렉션 >
과 <
같이 처리됩니다. 이로 인해 복잡한 비교 표현식 작성이 불편했습니다. [[
쉘 구문으로 만들어 져서 동 기적으로 구문 분석 될 수 있습니다. 내 [[
변수 단어 분할을하지 않는, <
그리고 >
, 비교 연산자로 사용할 수 =
등, 다음 매개 변수를 인용 여부에 따라 다르게 동작 할 수 있습니다이하는 모든 편의 시설 있습니다 [[
기존보다 사용하기 쉬운 [
명령 / 내장이.
[
수백만 스크립트에 호환되지 않는 변경이 있었기 때문에 이와 같은 구문으로 간단히 코딩 할 수 없었습니다 . [[
이전에는 없었던 새로운 구문 을 사용하여 이전 버전과 호환되는 방식으로 완전히 개선 할 수있었습니다.
이것은 $((...))
산술 표현식에 대한 구문을 가져온 진화와 유사하며 대부분 전통적인 expr
명령을 대체했습니다 .
답변
더 새로운 [[
에서이 bash
입니다 최적화 의 [
.
고전은 [
이 사소한 작업을 수행하는 자주 사용되는 경우, 하나의 큰 단점이있다 : 그것은 때마다 새로운 프로세스를 생성합니다 :
(그냥 비교하는 새로운 주소 공간을 생성 0
하고 1
!마다)
추가의 주요 요점은 [[
표현의 평가가 [
추가 프로세스를 생성하지 않도록 만드는 것이라고 생각합니다 . 그러나 일이 어떻게 [
변할 수 없었는가-많은 혼란과 문제를 야기 할 것입니다. 따라서 최적화는 새로운 이름,보다 효율적인 방식, 즉 쉘 내장 명령으로 구현되었습니다.
쉘 구문에서 키워드로 부작용이되었습니다.
당시 [
처음 사용 된 것은 외부 프로세스를 통해 올바른 방법이었습니다 .