Bash에서 단일 및 이중 대괄호의 차이점


161

나는 bash 예제를 읽고 if있지만 일부 예제는 대괄호로 작성됩니다.

if [ -f $param ]
then
  #...
fi

이중 대괄호가있는 기타 :

if [[ $? -ne 0 ]]
then
    start looking for errors in yourlog
fi

차이점은 무엇입니까?


3
이 질문에 대한 답변을보고 답을 얻을 수 있습니다 : unix.stackexchange.com/questions/3831/…
Amir Naghizadeh

답변:


188

[]posix 쉘 호환 조건 테스트는 단일 입니다.

Double [[]]은 표준에 대한 확장 []이며 bash 및 기타 쉘 (예 : zsh, ksh)에서 지원됩니다. 추가 작업 (표준 posix 작업)을 지원합니다. 예를 들어 : ||대신 -o정규 표현식과 일치합니다 =~. 차이점에 대한 전체 목록은 조건부 구문 에 대한 bash 매뉴얼 섹션에서 찾을 수 있습니다 .

[]쉘에서 스크립트를 이식 가능하게 할 때마다 사용하십시오 . [[]]조건식을 지원 []하지 않고 이식 가능하지 않은 경우 사용하십시오 .


6
스크립트가 명시 적으로 지원하는 쉘을 요청하는 shebang으로 시작하지 않으면 [[ ]](예 : bash with #!/bin/bash또는 #!/usr/bin/env bash) 휴대용 옵션을 사용해야한다고 덧붙였습니다 . / bin / sh가 이와 같은 확장을 지원한다고 가정하는 스크립트는 그렇지 않은 경우 최근 데비안 및 우분투 릴리스와 같은 OS에서 중단됩니다.
Gordon Davisson

87

행동 차이

Bash 4.3.11에서 테스트 :

  • POSIX vs Bash 확장 :

  • 정규 명령 대 마법

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

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

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

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

      특히, 경로 <재 지정이며 여러 명령을 연결 &&하고로 이스케이프하지 않는 한 서브 쉘을 생성 하며 단어 확장은 평소와 같이 수행됩니다.||( )\

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

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

      Bashese에서 : [내장 명령이며 [[키워드입니다 : /ubuntu/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? ]]: 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같은 !(.

bash 3.2 이상에서 4 이며 bash 3.1과의 호환성이 제공되지 않습니다 (와 같이 BASH_COMPAT=3.1)

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


3
" 내가 본 모든 [[]] 구성에 대해 POSIX 등가물이 있습니다. " 행성 표면의 어떤 튜링 컴플리트 (Turing Complete) 언어에 대해서도 같은 말을 할 수 있습니다 .
A. Rick

3
@ A.Rick은 모든 "언어 Y에서 X를 수행하는 방법"에 대한 올바른 답변이 될 것입니다. SO- : 물론, 그 말에는 "편리하게"암시 적입니다.
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功

6
환상적인 요약. 노력해 주셔서 감사합니다. 그러나 나는 추천에 동의하지 않습니다. 이식성과보다 일관되고 강력한 구문입니다. 사용자 환경에서 bash> 4를 요구할 수 있으면 [[]] 구문이 권장됩니다.
Bernard

@Downvoters 설명하고 정보를 향상시킬 수 있도록 설명하십시오 :-)
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功

8
대단한 답변이지만 권장 사항은 항상 사용[]선호하는 것으로 읽습니다 . 이식성을 잃고 싶지 않다면 사용 []하십시오 . 언급 한 바와 같이 여기 : POSIX 또는 본 셸에 휴대 / 적합성이 문제가되는 경우, 이전 구문을 사용해야합니다. 반면에 스크립트에 BASH, Zsh 또는 KornShell이 ​​필요한 경우 새 구문이 더 유연하지만 반드시 이전 버전과 호환되는 것은 아닙니다. 차라리 함께 가고 싶어 [[ ab =~ ab? ]]내가 할 수있는 경우와 것보다 이전 버전과의 호환성에 대한 염려가 없다printf 'ab' | grep -Eq 'ab?'
MauricioRobayo

14

조건 테스트를위한 단일 괄호 안에 (예 : [...]), single과 같은 일부 연산자 =는 모든 쉘에서 지원되는 반면, 연산자의 사용은 ==일부 이전 쉘에서는 지원되지 않습니다.

상태 검사 (예 : [[...]])에 대한 이중 대괄호 안에 사용 사이에는 차이가 없다 =거나 ==오래되거나 새로운 쉘있다.

편집 : 나는 또한 참고해야합니다 : bash에서는 가능한 경우 항상 대괄호 [[...]]를 사용하십시오. 단일 대괄호보다 안전하기 때문입니다. 다음 예제를 통해 이유를 설명하겠습니다.

if [ $var == "hello" ]; then

$ var이 null / 비어있는 경우 다음과 같이 스크립트에 표시됩니다.

if [ == "hello" ]; then

스크립트가 깨질 것입니다. 해결책은 큰 괄호를 사용하거나 항상 변수 주위에 따옴표를 묶는 것입니다 ( "$var"). 이중 괄호가 더 나은 방어 코딩 방식입니다.


1
하지 말아야 할 충분한 이유가없는 한 모든 변수 읽기 주위에 따옴표를 두는 것은 조건에있는 변수뿐만 아니라 모든 변수 읽기에 적용되기 때문에 훨씬 더 방어적인 코딩 방법입니다. 하드 드라이브 이름에 공백이 포함 된 경우 iTunes 설치 프로그램 버그로 인해 사람들의 파일이 삭제되었습니다. 또한 언급 한 문제를 해결합니다.
차이 티 렉스


1

다음과 같이 가벼운 정규식 일치에 이중 대괄호를 사용할 수 있습니다.

if [[ $1 =~ "foo.*bar" ]] ; then

(사용중인 bash 버전 이이 구문을 지원하는 한)


6
패턴을 인용 한 것을 제외하고는 이제 리터럴 문자열로 취급됩니다.
ormaaj

매우 사실입니다. 때때로 이것은 나를 괴롭힌다 :)
asf107

1

배쉬 매뉴얼 은 말한다 :

[[와 함께 사용하면 '<'및 '>'연산자는 현재 로케일을 사용하여 사전 순으로 정렬합니다. 테스트 명령은 ASCII 순서를 사용합니다.

(테스트 명령은 []와 동일합니다)

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