이중 또는 단일 괄호, 괄호, 중괄호를 사용하는 방법


658

Bash에서 대괄호, 괄호, 중괄호 사용 및 이중 또는 단일 형식의 차이점에 혼란 스럽습니다. 명확한 설명이 있습니까?

답변:


606

배쉬에서, test그리고는 [쉘 내장 명령입니다.

이중 브라켓 쉘 키워드입니다, 추가 기능을 사용할 수 있습니다. 예를 들어, 사용 &&하고 ||대신 -a과를 -o하고 정규 표현식 매칭 연산자가있다 =~.

또한 간단한 테스트에서 이중 대괄호는 단일 대괄호보다 훨씬 빠르게 평가되는 것으로 보입니다.

$ time for ((i=0; i<10000000; i++)); do [[ "$i" = 1000 ]]; done

real    0m24.548s
user    0m24.337s
sys 0m0.036s
$ time for ((i=0; i<10000000; i++)); do [ "$i" = 1000 ]; done

real    0m33.478s
user    0m33.478s
sys 0m0.000s

변수 이름을 구분하는 중괄호는 매개 변수 확장에 사용 되므로 다음과 같은 작업을 수행 할 수 있습니다.

  • 변수 내용 잘라 내기

    $ var="abcde"; echo ${var%d*}
    abc
  • 대체물과 유사하게 만들기 sed

    $ var="abcde"; echo ${var/de/12}
    abc12
  • 기본값 사용

    $ default="hello"; unset var; echo ${var:-$default}
    hello
  • 그리고 몇 가지 더

또한 중괄호 확장은 일반적으로 루프에서 반복되는 문자열 목록을 작성합니다.

$ echo f{oo,ee,a}d
food feed fad

$ mv error.log{,.OLD}
(error.log is renamed to error.log.OLD because the brace expression
expands to "mv error.log error.log.OLD")

$ for num in {000..2}; do echo "$num"; done
000
001
002

$ echo {00..8..2}
00 02 04 06 08

$ echo {D..T..4}
D H L P T

Bash 4 이전에는 선행 0 및 증분 기능을 사용할 수 없었습니다.

중괄호 확장에 대해 알려주는 gboffi에게 감사드립니다.

괄호는 산술 연산 에 사용 됩니다 .

((a++))

((meaning = 42))

for ((i=0; i<10; i++))

echo $((a + b + (14 * c)))

정수 및 배열 변수에서 달러 기호를 생략하고 가독성을 위해 연산자 주위에 공백을 포함시킬 수 있습니다.

단일 괄호는 배열 인덱스 에도 사용됩니다 .

array[4]="hello"

element=${array[index]}

오른쪽의 (대부분 / 모두?) 배열 참조에는 중괄호가 필요합니다.

ephemient의 의견에 따르면 괄호는 하위 셸 에도 사용됩니다. 그리고 그것들은 배열을 만드는 데 사용됩니다.

array=(1 2 3)
echo ${array[1]}
2

8
경고 :이 기능은 포크 폭탄이므로 실행하지 마십시오. 참조 : en.wikipedia.org/wiki/Fork_bomb
추후 공지가있을 때까지 일시 중지되었습니다.

3
추가로 호출하면 포크 폭탄 :입니다.
ephemient

7
또한 완성도를 위해 나는 오래된 스크립트에서 이것을 발견했습니다 $[expression]. 이것은 새로운 선호하는 구문에 대한 오래되고 더 이상 사용되지 않는 산술 표현 구문입니다.$((expression))
michael

2
@DennisWilliamson 중괄호를 사용하는 또 다른 용도는 bash아래에서 주변에 언급 된 것처럼 시퀀스를 만드는 것입니다 ( stackoverflow.com/a/8552128/2749397 )이 기능에 대해 조금 언급하고 싶습니다 (; 언급하지 않았지만 ;-) m 가장 많이 투표 된 답변을 탈것으로 사용하는 자유를 취함 ... 시퀀스 리터럴의 두 가지 예 : echo {01..12}-> 01 02 03 04 05 06 07 08 09 10 11 12(초기 0에 유의하십시오); echo {C..Q}-> C D E F G H I J K L M N O P Q. 주요 용도는 다음과 같습니다. 예 : for cnt in {01..12} ; do ... ${cnt} ... ; done
gboffi

1
@gboffi : 제로 패딩 기능은 Bash 4에서 사용할 수있게되었습니다. 또한 Bash 4에서는 echo {01..12..2}-> "01 03 05 07 09 11" 순서로 증분을 지정할 수 있습니다 . 시퀀스에 대해 상기시켜 주셔서 감사합니다. 내 답변에 추가하겠습니다.
추후 공지가있을 때까지 일시 중지되었습니다.

336
  1. 단일 괄호 ( [)는 일반적으로 실제로 이름이 지정된 프로그램을 호출합니다 [. man test또는 man [자세한 내용은. 예:

    $ VARIABLE=abcdef
    $ if [ $VARIABLE == abcdef ] ; then echo yes ; else echo no ; fi
    yes
  2. 이중 괄호 ( [[)는 기본적으로 단일 괄호와 동일한 기능을 수행하지만 bash 내장입니다.

    $ VARIABLE=abcdef
    $ if [[ $VARIABLE == 123456 ]] ; then echo yes ; else echo no ; fi
    no
  3. 괄호 ( ())는 서브 쉘을 작성하는 데 사용됩니다. 예를 들면 다음과 같습니다.

    $ pwd
    /home/user 
    $ (cd /tmp; pwd)
    /tmp
    $ pwd
    /home/user

    보다시피, 서브 쉘을 사용하면 현재 쉘의 환경에 영향을주지 않고 작업을 수행 할 수 있습니다.

  4. (a) 괄호 ( {})는 변수를 명확하게 식별하는 데 사용됩니다. 예:

    $ VARIABLE=abcdef
    $ echo Variable: $VARIABLE
    Variable: abcdef
    $ echo Variable: $VARIABLE123456
    Variable:
    $ echo Variable: ${VARIABLE}123456
    Variable: abcdef123456

    (b) 중괄호는 또한 현재 쉘 컨텍스트 에서 일련의 명령을 실행하는 데 사용됩니다.

    $ { date; top -b -n1 | head ; } >logfile 
    # 'date' and 'top' output are concatenated, 
    # could be useful sometimes to hunt for a top loader )
    
    $ { date; make 2>&1; date; } | tee logfile
    # now we can calculate the duration of a build from the logfile

( )그래도 미묘한 문법 차이가있다 ( bash 참조 ). 본질적으로, 세미콜론 ;중괄호 내 마지막 명령 다음은 필수이며, 중괄호 {, } 있어야 공백으로 둘러싸여.


26
글쎄, [실제로 Bash에 내장되어 있지만 내장에 /bin/[반대되는 것처럼 행동해야합니다 [[. [[더 논리적 인 연산 및 다른 인용 역할과 같은 다른 기능이 있습니다. 또한 단일 괄호는 배열, 프로세스 대체 및 확장 글로브에도 사용됩니다. 이중 괄호는 산술에 사용됩니다. 중괄호 {}는 명령 그룹화 또는 여러 유형의 매개 변수 확장 또는 중괄호 확장 또는 시퀀스 확장에 사용됩니다. 나는 다른 용도도 놓쳤다 고 확신한다 ...
ephemient

4
이 표현에서 이중-동일은 if [ $VARIABLE == abcdef ]bashism입니다. 비록 작동하더라도 피해야합니다. 명시 적으로 bash ( if [[ ...==...]])를 사용하거나보다 전통적인 조건부 ( if [ "$VARIABLE" = "abcdef" ])를 사용하고 있음을 분명히하십시오 . 논란의 여지가 있지만 스크립트는 bash와 관련된 기능이 필요할 때까지 가능한 한 간단하고 이식성이 뛰어나야합니다. 그러나 어쨌든 의도는 분명해야한다. "="및 "=="및 "[["및 "["는 다르게 작동하며 사용법이 일관되어야합니다.
마이클

3
@michael_n :이 말에 +1. 참고로, 스크립팅을 좋아하지만 이식 가능한 방법은 [ "$var" = ".."]대신 대신 테스트하는 것이 좋지만 ==C에서는 테스트 대신 할당하고 버그의 일반적인 원인은 무엇입니까? 't은 test사용하는 ==대신 =? 누구 알아?
Olivier Dulac

또한 (적어도 쿠분투에서는) 명령 /usr/bin/[이에 대한 심볼릭 링크가 아닌 재미있는 것들이 /usr/bin/test있습니다.이 프로그램들은 크기가 다릅니다!
Hi-Angel

또한 : 단일 닫는 괄호 )case케이스 라인을 끝내기위한 명령문 구문의 일부입니다 . 여는 괄호가 없습니다. 내가 처음봤을 때 날 버렸다.
Agustín Amenabar

302

브라켓

if [ CONDITION ]    Test construct  
if [[ CONDITION ]]  Extended test construct  
Array[1]=element1   Array initialization  
[a-z]               Range of characters within a Regular Expression
$[ expression ]     A non-standard & obsolete version of $(( expression )) [1]

[1] http://wiki.bash-hackers.org/scripting/obsolete

중괄호

${variable}                             Parameter substitution  
${!variable}                            Indirect variable reference  
{ command1; command2; . . . commandN; } Block of code  
{string1,string2,string3,...}           Brace expansion  
{a..z}                                  Extended brace expansion  
{}                                      Text replacement, after find and xargs

괄호

( command1; command2 )             Command group executed within a subshell  
Array=(element1 element2 element3) Array initialization  
result=$(COMMAND)                  Command substitution, new style  
>(COMMAND)                         Process substitution  
<(COMMAND)                         Process substitution 

괄호

(( var = 78 ))            Integer arithmetic   
var=$(( 20 + 5 ))         Integer arithmetic, with variable assignment   
(( var++ ))               C-style variable increment   
(( var-- ))               C-style variable decrement   
(( var0 = var1<98?9:21 )) C-style ternary operation

@Yola, $ (varname)가 정확히 무엇인지 설명해 주시겠습니까? Apple Xcode 프로젝트에서 파일 경로를 스크립트 입력 / 출력으로 지정할 수 있습니다. $ SRC_ROOT / myFile.txt 또는 $ {SRC_ROOT} /myFile.txt를 지정하면 (SRC_ROOT var는 빌드 시스템에서 내보냄)-작동하지 않습니다. $ (SRC_ROOT) /myFile.txt 만 작동합니다. 이유가 무엇입니까? 분명히 var name은 명령이 아니십니까?
Motti Shneor

1
귀하의 경우 @MottiShneor $(varname)는 bash 구문과 관련이 없습니다. Makefile 구문의 일부입니다 .
사샤

그렇지 않습니다-Xcode가 makefile을 사용하여 빌드하지 않으며 해당 변수는 환경 변수입니다. 독점 Xcode 빌드 시스템 프로세스는 이러한 사전 정의 된 환경 변수의 값을 읽습니다. 사용자 정의 빌드 단계는 일반적인 쉘 스크립트 (bash 또는 기타) 일 뿐이며 동일한 var에 액세스 할 수 있습니다.
Motti Shneor 11

@MottiShneor, 알았어, 구체화하자 : 아마도 xcconfig 구문의 일부일 것이다 . 어쨌든 $(varname)귀하의 경우 bash 구문과 관련이 없습니다.
사샤

테스트 구성과 확장 테스트 구성의 차이점이 무엇인지 언급하지 않았습니다.
Nikos

23

방금 TLDP 에서 이것을 추가하고 싶었 습니다 .

~:$ echo $SHELL
/bin/bash

~:$ echo ${#SHELL}
9

~:$ ARRAY=(one two three)

~:$ echo ${#ARRAY}
3

~:$ echo ${TEST:-test}
test

~:$ echo $TEST


~:$ export TEST=a_string

~:$ echo ${TEST:-test}
a_string

~:$ echo ${TEST2:-$TEST}
a_string

~:$ echo $TEST2


~:$ echo ${TEST2:=$TEST}
a_string

~:$ echo $TEST2
a_string

~:$ export STRING="thisisaverylongname"

~:$ echo ${STRING:4}
isaverylongname

~:$ echo ${STRING:6:5}
avery

~:$ echo ${ARRAY[*]}
one two one three one four

~:$ echo ${ARRAY[*]#one}
two three four

~:$ echo ${ARRAY[*]#t}
one wo one hree one four

~:$ echo ${ARRAY[*]#t*}
one wo one hree one four

~:$ echo ${ARRAY[*]##t*}
one one one four

~:$ echo $STRING
thisisaverylongname

~:$ echo ${STRING%name}
thisisaverylong

~:$ echo ${STRING/name/string}
thisisaverylongstring

18
세 개의 요소를 포함하는 것이 아니라 세 개의 문자를 포함하는 세 번째 문자로 echo ${#ARRAY}인해 세 개 를 표시하는 마음 ARRAY! 요소 수를 인쇄하려면을 사용하십시오 echo ${#ARRAY[@]}.
TrueY

변수 가 존재 하면 @zeal ${TEST:-test}은 같고 그렇지 않으면 단순히 문자열 "test"를 반환합니다. 더 많은 기능을하는 또 다른 버전이 있습니다 : --- TEST가 존재 하는 경우 와 동일 하지만, 존재하지 않을 때마다 변수를 생성하고 "test"라는 값을 할당하며 전체 표현식의 값이됩니다. $TESTTEST${TEST:=test}$TESTTEST
확률을 좋아한다

18

간의 차이 테스트 , [ 그리고 [ 좋은 세부 설명한다 BashFAQ .

간단히 말해 : 테스트는 명령의 이전 구문을 구현합니다. 거의 모든 쉘에서 (가장 오래된 Bourne 쉘은 예외입니다), [는 테스트의 동의어입니다 (그러나 마지막 인수는]이 필요합니다). 모든 최신 쉘에는 [의 내장 구현이 있지만 일반적으로 / bin / [와 같은 해당 이름의 외부 실행 파일이 여전히 있습니다.

[[이 프로그램의 새로운 개선 된 버전은 프로그램이 아니라 키워드입니다. 이것은 아래와 같이 사용의 용이성에 유리한 영향을 미칩니다. [[KornShell 및 BASH (예 : 2.03)는 이해하지만 이전 POSIX 또는 BourneShell은 이해하지 않습니다.

그리고 결론 :

새로운 테스트 명령은 언제 사용해야합니까? BourneShell 로의 이식성이 문제가되는 경우 이전 구문을 사용해야합니다. 반면에 스크립트에 BASH 또는 KornShell이 ​​필요한 경우 새 구문이 훨씬 유연합니다.


18

함수 정의의 괄호

()함수 정의에 괄호 가 사용되고 있습니다 :

function_name () { command1 ; command2 ; }

이것이 명령 매개 변수에서도 괄호를 피해야하는 이유입니다.

$ echo (
bash: syntax error near unexpected token `newline'

$ echo \(
(

$ echo () { command echo The command echo was redefined. ; }
$ echo anything
The command echo was redefined.

오, 나는 csh를 시험해 보았다. 내 잘못이야. bash를 시도하면 작동합니다. bash의 'command'명령을 몰랐습니다.
Chan Kim

echo () 명령의 재정의를 어떻게 취소 할 수 있습니까? (bash를 다시 열지 않고)
Chan Kim

2
@ChanKim : unset -f echo. 참조하십시오 help unset.
pabouk

0
Truncate the contents of a variable

$ var="abcde"; echo ${var%d*}
abc

Make substitutions similar to sed

$ var="abcde"; echo ${var/de/12}
abc12

Use a default value

$ default="hello"; unset var; echo ${var:-$default}
hello

당신이 질문에 대답 할 때, 단지 "코드"를 목표로하지 말고 설명을 추가하려고 노력하십시오.
Mikev
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.