tags:

views:

1050

answers:

3

Hi,

I am confused by the usage of bracket, parentheses, curly braces in Bash, as well as the difference between their double or single forms. Is there a clear explanation?

Thanks and regards!

+4  A: 
  1. A single bracket ([) usually actually calls program named [; man test or man [ for more info. Example:

    $ VARIABLE=abcdef
    $ if [ $VARIABLE == abcdef ] ; then echo yes ; else echo no ; fi
    yes
    
  2. The double bracket ([[) does the same thing (basically) as a single bracket, but is a bash builtin.

    $ VARIABLE=abcdef
    $ if [[ $VARIABLE == 123456 ]] ; then echo yes ; else echo no ; fi
    no
    
  3. Parentheses (()) are used to create a subshell. For example:

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

    As you can see, the subshell allowed you to perform operations without affecting the environment of the current shell.

  4. Braces ({}) are used to unambiguously identify variables. Example:

    $ VARIABLE=abcdef
    $ echo Variable: $VARIABLE
    Variable: abcdef
    $ echo Variable: $VARIABLE123456
    Variable:
    $ echo Variable: ${VARIABLE}123456
    Variable: abcdef123456
    
Carl Norum
Well, `[` is actually a builtin in Bash, but it is supposed to act like `/bin/[` as opposed to the `[[` builtin. `[[` has different features, like more logical operations and different quoting roles. Additionally: single parentheses are also used for arrays, process substitution, and extended globs; double parentheses are used for arithmetic; curly braces `{}` are used for command grouping or multitudes of types of parameter expansion or brace expansion or sequence expansion. I'm sure I've missed some other uses too...
ephemient
Good catch. There are a million of 'em.
Carl Norum
+9  A: 

In Bash, test and [ are builtins.

The double bracket enables additional functionality. For example, you can use && and || instead of -a and -o and there's a regular expression matching operator =~.

The braces, in addition to delimiting a variable name are used for parameter expansion so you can do things like:

  • 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

  • and several more

Double parentheses are used for arithmetic operations:

((a++))

((meaning = 42))

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

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

and they enable you to omit the dollar signs on integer and array variables and include spaces around operators for readability.

Single brackets are also used for array indices:

array[4]="hello"

element=${array[index]}

Curly brace are required for (most/all?) array references on the right hand side.

ephemient's comment reminded me that parentheses are also used for subshells. And that they are used to create arrays.

array=(1 2 3)
echo ${array[1]}
2
Dennis Williamson
`[ -e * ]` and `[[ -e * ]]` are very different, which is rather unfortunate. Curlies are used in `a{b,c,d}e` and `k{1..9}` and for grouping commands without a subshell `foo
ephemient
WARNING: That function is a fork bomb, do not run it. See: http://en.wikipedia.org/wiki/Fork_bomb
Dennis Williamson
It's only a fork bomb if you invoke it with an additional `:`.
ephemient
A: 

I just wanted to add these from 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
kzh