Bash Cheatsheet
Arrays
Use this Bash reference while you build software engineering projects, review code for technical interview prep, or polish examples for a software engineer resume.
Indexed Arrays — Declaration and Assignment
# Literal assignment arr=("apple" "banana" "cherry") # Declare then assign declare -a arr arr[0]="first" arr[1]="second" arr[5]="sixth" # sparse: indices 2-4 don't exist # Append arr+=("new item") arr+=("x" "y") # append multiple # From command output arr=( $(ls *.txt) ) # word-split (fails with spaces in names) mapfile -t arr < <(ls *.txt) # safer: one element per line readarray -t arr < file.txt # alias for mapfile
Accessing Elements
arr=("a" "b" "c" "d") echo ${arr[0]} # first element: "a" echo ${arr[-1]} # last element: "d" (Bash 4.3+) echo ${arr[-2]} # second to last: "c" echo ${arr[@]} # all elements (each quoted separately) echo ${arr[*]} # all elements (joined with IFS when quoted) echo "${arr[@]:1:2}" # slice: elements 1 and 2 → "b c" echo "${arr[@]: -2}" # last 2 elements → "c d" echo ${#arr[@]} # number of elements: 4 echo ${#arr[2]} # length of element at index 2: 1 echo ${!arr[@]} # all indices: 0 1 2 3
Iterating Arrays
arr=("red" "green" "blue") # Iterate values for item in "${arr[@]}"; do echo "$item" done # Iterate with index for i in "${!arr[@]}"; do echo "[$i] = ${arr[$i]}" done # C-style with length for (( i=0; i<${#arr[@]}; i++ )); do echo "$i: ${arr[$i]}" done
Modifying Arrays
arr=("a" "b" "c" "d") # Set element arr[1]="B" # Append single arr+=("e") # Append multiple arr+=("f" "g") # Delete element (leaves hole — index remains, value becomes empty) unset arr[2] echo "${arr[@]}" # a B d e f g (gap at index 2) echo "${!arr[@]}" # 0 1 3 4 5 6 (index 2 gone) # Re-index to fill holes arr=( "${arr[@]}" ) # Delete entire array unset arr # Slice (copy subset) slice=( "${arr[@]:1:3}" ) # elements 1,2,3 # Sort (no built-in; use a subshell + printf trick) IFS=$'\n' sorted=($(sort <<< "${arr[*]}"))
Array Manipulation Patterns
arr=("apple" "banana" "cherry" "date") # Reverse reversed=() for (( i=${#arr[@]}-1; i>=0; i-- )); do reversed+=("${arr[$i]}") done # Filter (keep matching) filtered=() for item in "${arr[@]}"; do [[ "$item" == *a* ]] && filtered+=("$item") done echo "${filtered[@]}" # apple banana date # Map (transform) upper=() for item in "${arr[@]}"; do upper+=("${item^^}") done # Join with delimiter (IFS=','; echo "${arr[*]}") # apple,banana,cherry,date printf '%s,' "${arr[@]}" # apple,banana,cherry,date, (trailing comma) printf '%s\n' "${arr[@]}" | paste -sd, # clean join
Associative Arrays (Bash 4+)
# Must explicitly declare declare -A map # Assign map["key"]="value" map[host]="localhost" map[port]="5432" # Literal initialization declare -A colors=( [red]="#ff0000" [green]="#00ff00" [blue]="#0000ff" ) # Access echo ${map[host]} # localhost echo ${map["key"]} # value echo ${map[missing]} # empty string (no error) # All keys echo ${!map[@]} # host port key # All values echo ${map[@]} # values in unspecified order # Count echo ${#map[@]} # 3 # Check if key exists [[ -v map[host] ]] && echo "host is set" [[ ${map[host]+x} ]] && echo "host is set" # POSIX-ish # Delete a key unset map[port] # Delete all unset map
Iterating Associative Arrays
declare -A scores=([alice]=95 [bob]=82 [carol]=91) # Values for val in "${scores[@]}"; do echo "$val" done # Keys for key in "${!scores[@]}"; do echo "$key" done # Key-value pairs for key in "${!scores[@]}"; do echo "$key = ${scores[$key]}" done # Sorted by key for key in $(echo "${!scores[@]}" | tr ' ' '\n' | sort); do echo "$key: ${scores[$key]}" done
mapfile / readarray
# Read lines of a file into array (Bash 4+) mapfile -t lines < file.txt readarray -t lines < file.txt # same thing # From command mapfile -t files < <(find . -name "*.sh") # With offset (start at index 2) mapfile -t -O 2 arr < file.txt # With count (read only 5 lines) mapfile -t -n 5 arr < file.txt # Callback on each line mapfile -t -C 'process_line' -c 1 arr < file.txt echo "${lines[0]}" # first line echo "${#lines[@]}" # total lines
Array Copying and Passing
orig=("x" "y" "z") # Copy array copy=("${orig[@]}") # Pass to function as arguments process() { local -a local_arr=("$@") echo "${local_arr[@]}" } process "${orig[@]}" # Pass by name (nameref, Bash 4.3+) process_ref() { declare -n _arr=$1 echo "${_arr[@]}" } process_ref orig # Return array from function via nameref get_data() { declare -n _out=$1 _out=("result1" "result2") } declare -a output get_data output echo "${output[@]}"
Common Gotchas
arr=("a" "b" "c") # WRONG: missing quotes causes word splitting for i in ${arr[@]}; do ... # breaks on elements with spaces # RIGHT: for i in "${arr[@]}"; do ... # WRONG: $arr alone expands to only arr[0] echo $arr # only "a" echo ${arr} # only "a" # RIGHT: echo "${arr[@]}" # all elements # Sparse arrays — length vs max index arr[100]="late" echo ${#arr[@]} # 1 (one element), not 101 echo ${!arr[@]} # 100 (the actual index) # [[ -v ]] is the right way to check element existence [[ -v arr[5] ]] && echo "index 5 exists"