bash에서 이중 대괄호와 단일 대괄호의 차이점은 무엇입니까?


426

방금 차이점이 정확히 무엇인지 궁금했습니다.

[[ $STRING != foo ]]

[ $STRING != foo ]

후자는 posix를 준수하고 sh에서 발견되고 전자는 bash에서 발견되는 확장입니다.


1
예를 들어, if문장 의 맥락에서 대괄호를 사용하지 않는 것에 대해 궁금한 경우 mywiki.wooledge.org/BashPitfalls#if_.5Bgrep_foo_myfile.5D
Kev

또한 우분투의 문서에서 : wiki.ubuntu.com/…
radistao

답변:


309

몇 가지 차이점이 있습니다. 제 생각에는 가장 중요한 몇 가지는 다음과 같습니다.

  1. [Bash와 다른 많은 현대 쉘에 내장되어 있습니다. 내장 [test폐쇄의 추가 요구 사항과 유사합니다 ]. 내장 매크로 [test기능을 모방 /bin/[하고 /bin/test자신의 한계와 함께 스크립트는 이전 버전과 호환 될 수 있도록. 원본 실행 파일은 여전히 ​​대부분 POSIX 호환 및 이전 버전과의 호환성을 위해 존재합니다. type [Bash 에서 명령 을 실행하면 [기본적으로 기본 제공되는 것으로 해석됩니다. (참고 : which [단지에 실행 파일을 찾습니다 PATH 와 동등하다 type -p [)
  2. [[호환되지는 않지만 어떤 /bin/sh점에서도 작동하지는 않습니다 . 그래서 [[더 현대적인 배쉬 / zsh을 / 가능한 ksh 옵션입니다.
  3. 때문에 [[쉘에 내장되어 기존의 요구 사항이 없습니다, 당신은에 따라 단어 분할에 대해 걱정할 필요가 없습니다 IFS의 공백 문자열로 평가 변수에 대한 혼란 최대 변수입니다. 따라서 변수를 큰 따옴표로 묶을 필요는 없습니다.

대부분의 경우 나머지는 더 좋은 구문입니다. 더 많은 차이점을 보려면 FAQ 답변으로 연결되는 것이 좋습니다. test, [와 [[? . 실제로 bash 스크립팅에 대해 진지한 경우 FAQ, 함정 및 안내서를 포함한 전체 위키를 읽는 것이 좋습니다 . 가이드 섹션의 테스트 섹션에서는 이러한 차이점에 대해 설명 하고 이식성이 뛰어 나기 위해 걱정할 필요가없는 경우 저자 가 더 나은 선택을하는 이유를 설명합니다 . 주요 이유는 다음과 같습니다.[[

  1. 테스트의 왼쪽을 인용하여 실제로 변수로 읽도록 걱정할 필요는 없습니다.
  2. < >입력 리디렉션으로 평가되지 않기 위해 백 슬래시 보다 작거나 크게 벗어날 필요가 없으므로 파일을 덮어 써서 실제로 물건을 엉망으로 만들 수 있습니다. 이것은 다시 [[기본 제공 으로 돌아갑니다 . [(test)가 외부 프로그램 인 경우, 쉘은 평가하는 방식 <과 호출되는 >경우에만 예외를 만들어야 /bin/test하는데 이는 실제로 의미가 없습니다.

5
감사합니다, bash FAQ에 대한 링크는 내가 찾던 것입니다 (해당 페이지에 대해 몰랐습니다).
0x89

2
이 정보로 게시물을 수정했지만 [및 테스트는 기본 제공으로 실행됩니다. 내장은 / bin / [및 / bin / test를 대체하도록 설계되었지만 바이너리의 한계도 재현해야했습니다. 'type ['명령은 내장이 사용되는지 확인합니다. '이 ['는 PATH에서 실행 파일 만 검색하며 'type -P ['
klynch

133

한마디로 :

[bash 내장입니다

[[]]은 강타 키워드입니다

키워드 : 키워드는 기본 제공과 매우 유사하지만 가장 큰 차이점은 특별한 구문 분석 규칙이 적용된다는 것입니다. 예를 들어, [는 bash 내장이고, [[는 bash 키워드입니다.) 그것들은 둘 다 물건을 테스트하는 데 사용되지만 [[는 내장이 아닌 키워드이므로 몇 가지 특별한 구문 분석 규칙의 이점을 통해 훨씬 쉽게 만들 수 있습니다.

  $ [ a < b ]
 -bash: b: No such file or directory
  $ [[ a < b ]]

bash는 파일 b를 명령 [a]로 경로 재 지정하려고하기 때문에 첫 번째 예제는 오류를 리턴합니다. 두 번째 예는 실제로 예상대로 수행합니다. <문자는 더 이상 File Redirection 연산자의 특별한 의미가 없습니다.

출처 : http://mywiki.wooledge.org/BashGuide/CommandsAndArguments


3
[POSIX 쉘 명령입니다. 내장되어있을 필요는 없습니다. ]구문이 균형을 이루도록 명령이 찾는 인수 일뿐입니다. 이 명령은 닫기를 찾지 않는 test것을 제외하고 동의어입니다 . test]
Kaz


81

행동 차이

Bash 4.3.11과의 차이점 :

  • POSIX vs Bash 확장 :

  • 정규 명령 대 마법

    • [ 이상한 이름을 가진 일반적인 명령입니다.

      ][추가 인수가 사용되지 않도록 하는 인수입니다 .

      우분투 16.04는 실제로 /usr/bin/[coreutils 가 제공 하는 실행 파일을 가지고 있지만 bash 내장 버전이 우선합니다.

      Bash가 명령을 구문 분석하는 방식에는 아무런 변화가 없습니다.

      특히, <리디렉션입니다, &&그리고 ||여러 명령을 연결, ( )하지 않는 한에서 탈출 서브 쉘을 생성 \하고, 단어 확장은 평소와 같이 발생합니다.

    • [[ X ]]X마술처럼 파싱 하는 단일 구문입니다. <, &&, ||()특수 처리, 워드 분할 규칙이 다릅니다된다.

      같은 더 차이도있다 =하고 =~.

      Bashese에서 : [내장 명령이며 [[키워드입니다 : https://askubuntu.com/questions/445749/whats-the-difference-between-shell-builtin-and-shell-keyword

  • <

  • &&||

    • [[ a = a && b = b ]]: 진실하고 논리적 이며
    • [ a = a && b = b ]: &&AND 명령 구분자로 구문 분석 된 구문 오류cmd1 && cmd2
    • [ a = a -a b = b ]: POSIX³에서는 동일하지만 더 이상 사용되지 않습니다.
    • [ a = a ] && [ b = b ]: POSIX 및 신뢰할 수있는 제품
  • (

    • [[ (a = a || a = b) && a = b ]]: 거짓
    • [ ( a = a ) ]: 구문 오류, ()서브 쉘로 해석
    • [ \( a = a -o a = b \) -a a = b ]: 동등하지만 ()POSIX에서 사용되지 않습니다.
    • { [ a = a ] || [ a = b ]; } && [ a = b ]POSIX 상당 5
  • 확장시 단어 분할 및 파일 이름 생성 (분할 + 글로브)

    • x='a b'; [[ $x = 'a b' ]]: 따옴표가 필요하지 않습니다.
    • x='a b'; [ $x = 'a b' ]: 구문 오류, 확장 [ a b = 'a b' ]
    • x='*'; [ $x = 'a b' ]: 현재 디렉토리에 둘 이상의 파일이 있으면 구문 오류가 발생합니다.
    • x='a b'; [ "$x" = 'a b' ]: POSIX 상당
  • =

    • [[ ab = a? ]]: 패턴 일치를 수행하기 때문에 true입니다 ( * ? [매직). 현재 디렉토리의 파일로 확장하지 않습니다.
    • [ ab = a? ]: a?글로브가 확장됩니다. 따라서 현재 디렉토리의 파일에 따라 true 또는 false 일 수 있습니다.
    • [ ab = a\? ]: false, glob 확장이 아님
    • ===모두 동일 [하고 [[있지만, ==배쉬 확장입니다.
    • case ab in (a?) echo match; esac: POSIX 상당
    • [[ ab =~ 'ab?' ]]: 거짓 4 , 마법을 잃는다''
    • [[ ab? =~ 'ab?' ]]: 사실
  • =~

    • [[ ab =~ ab? ]]: true, POSIX 확장 정규식 일치, ?확장하지 않음
    • [ a =~ a ]: 구문 오류. bash와 동등한 것은 없습니다.
    • printf 'ab\n' | grep -Eq 'ab?': POSIX 동등 (단일 데이터 만)
    • awk 'BEGIN{exit !(ARGV[1] ~ ARGV[2])}' ab 'ab?': POSIX 상당.

권장 사항 : 항상 사용하십시오 [].

[[ ]]내가 본 모든 구성에 대해 POSIX 등가물 이 있습니다.

당신이 당신을 사용하는 경우 [[ ]]:

  • 휴대 성을 잃다
  • 독자가 다른 배쉬 확장의 복잡성을 배우도록 강요하십시오. [이상한 의미를 가진 일반적인 명령이며 특별한 의미가 없습니다.

¹ [[...]]Korn 쉘 의 동등한 구성에서 영감을 받음

² 그러나 a또는 b(와 같은 +또는 index) 의 일부 값에는 실패하고 10 진수 정수 a와 같으면 숫자 비교를 수행합니다 b. expr "x$a" '<' "x$b"둘 다 해결합니다.

³도의 일부 값 실패 ab같은 !(.

4 떠들썩한 파티 3.2 이상 및 3.1 날리고 제공 호환성 (와 같이 사용할 수 없습니다 BASH_COMPAT=3.1)

5 및 쉘 연산자 ( 및 연산자 또는 / 연산자 와 반대 )가 동일한 우선 순위를 갖기 때문에 그룹화 (여기서 {...;}명령 그룹을 사용 (...)하여 불필요한 서브 쉘을 실행 함)는 필요하지 않습니다 . 따라서 동일합니다.||&&||&& [[...]]-o-a [[ a = a ] || [ a = b ] && [ a = b ]


printf 'ab' | grep -Eq 'ab?'내 에서 사용하는 방법 if [ … ]?
meeDamian

1
@meeDamian if ( printf 'ab' | grep -Eq 'a' ); then echo 'a'; fi. []같은 명령 grep입니다. 은 ()해당 명령에 필요하지 않을 수도 잘 모르겠어요 : 나는 때문에의를 추가 |, 배쉬 일을 구문 분석 방법에 따라 달라집니다. 없다면 |나는 당신이 그냥 쓸 수 있다고 확신합니다 if cmd arg arg; then.
Ciro Santilli 新疆 改造 中心 法轮功 六四 事件


1
좋은 목록! 참조 : wiki.ubuntu.com/...이
radistao

5

단일 브래킷[], 조건식을 묶는 데 POSIX 셸을 준수합니다.

이중 브래킷 ([[]], 표준 POSIX 버전의 확장 (또는 확장) 버전)은 bash 및 기타 쉘 (zsh, ksh)에서 지원됩니다.

배쉬에서, 우리가 사용하는 숫자 비교를 위해 eq, ne, lt그리고 gt비교를 위해 두 배 브래킷, 우리가 사용할 수있는 ==, !=, <,>문자 그대로.

  • [테스트 명령의 동의어입니다. 쉘에 내장되어 있어도 새로운 프로세스를 생성합니다.
  • [[ 프로그램이 아닌 키워드 인 새로운 개선 된 버전입니다.

예를 들면 다음과 같습니다.

[ var1 lt var2] #works
[ var1 < var2] #error: var2 No such file or directory 
[ var1 \< var2] #works with escape
[[ var1 < var2]] #works

4

맨 페이지의 관련 섹션을 빠르게 읽으면 주요 차이점은 ==and !=연산자가 리터럴 문자열이 아닌 패턴과 일치하고 =~정규 표현식 비교 연산자가 있다는 것입니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.