Mastering Bash Brackets: Parentheses, Brackets, and Brace Expansions Explained
This guide provides a comprehensive overview of Bash’s various bracket types—including parentheses, double parentheses, square brackets, double square brackets, and curly braces—detailing their syntax, typical use‑cases, parameter‑expansion forms, pattern‑matching capabilities, and practical code examples for effective shell scripting.
Parentheses ()
Single parentheses create a subshell; commands inside are executed sequentially and variables defined there are not visible outside. Multiple commands are separated by semicolons, and the final command may omit the trailing semicolon.
Command substitution using $(cmd) runs cmd and replaces the expression with its standard output (similar to back‑ticks, though not supported by all shells such as tcsh).
Parentheses are also used for array initialization, e.g., array=(a b c d).
Double Parentheses (( ))
Double parentheses perform integer arithmetic. The expression ((exp)) evaluates a C‑style arithmetic expression; a zero result returns exit status 1 (false), any non‑zero result returns 0 (true). Logical expressions follow the same rule.
All C‑compatible operators, including the ternary operator, are allowed. Base conversion is supported, e.g., echo $((16#5f)) outputs 95.
Variables can be incremented directly, e.g., a=5; ((a++)) sets a to 6.
Within double parentheses, variable names need not be prefixed with $. Multiple expressions can be separated by commas, enabling constructs such as for ((i=0;i<5;i++)) or if ((i<5)).
Square Brackets []
Single square brackets are Bash built‑ins equivalent to the test command. They evaluate conditional expressions and return an exit status based on the result. In modern Bash, the closing bracket is required.
String comparison operators are == and !=; integer comparison uses -eq, -gt, etc. Logical AND/OR are expressed as -a and -o. The < and > symbols are not valid for numeric comparison without escaping.
Square brackets also denote character ranges in regular expressions, though they cannot be used for regex inside test.
When accessing arrays, array[2] retrieves the element at index 2.
Double Square Brackets [[ ]]
Double brackets are a Bash keyword, not a command. Inside [[ … ]], pathname expansion and word splitting are suppressed, while parameter expansion and command substitution still occur.
They support pattern matching with =~ for regular expressions. For example, [[ hello == hell? ]] evaluates to true.
Logical operators &&, ||, <, and > work directly inside the construct, allowing expressions like if [[ $a != 1 && $a != 2 ]].
Variables inside [[ … ]] do not need the $ prefix when used in arithmetic or pattern contexts.
Curly Braces { }
Brace expansion performs filename globbing. Comma‑separated lists generate multiple filenames, e.g., touch {a,b}.txt creates a.txt and b.txt. Ranges such as {a..d} expand to sequential names.
When used as a command group, braces create an anonymous function that runs in the current shell, so variables remain available after the block. Commands inside must be terminated with semicolons, and a space is required after the opening brace.
Parameter‑expansion forms include: ${var:-string} – use string if var is unset or null. ${var:=string} – assign string to var if it is unset or null. ${var:+string} – substitute string only when var is set. ${var:?string} – print string to stderr and exit if var is unset or null.
Pattern‑based substitution forms: ${var%pattern} – remove the shortest matching suffix. ${var%%pattern} – remove the longest matching suffix. ${var#pattern} – remove the shortest matching prefix. ${var##pattern} – remove the longest matching prefix. ${var/pattern/repl} – replace first occurrence of pattern with repl. ${var//pattern/repl} – replace all occurrences.
String extraction syntax: ${var:num} – extract from position num to the end (positive counts from the left, negative from the right). ${var:num1:num2} – extract num2 characters starting at num1.
Practical Examples
if ((i<5))
if [ $i -lt 5 ]
if [ $a -ne 1 -a $a != 2 ]
if [[ $a != 1 && $a != 2 ]]
for i in $(seq 0 4); do echo $i; done
for ((i=0;i<5;i++)); do echo $i; doneParameter‑expansion demonstrations:
var=testcase
echo ${var%*e} # removes shortest suffix matching *e → testca
echo ${var%%s*e} # removes longest suffix matching s*e → te
echo ${var#?e} # removes shortest prefix matching ?e → stcaseThese constructs together provide powerful mechanisms for writing concise, readable, and efficient Bash scripts.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Liangxu Linux
Liangxu, a self‑taught IT professional now working as a Linux development engineer at a Fortune 500 multinational, shares extensive Linux knowledge—fundamentals, applications, tools, plus Git, databases, Raspberry Pi, etc. (Reply “Linux” to receive essential resources.)
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
