Advanced Bash: Arrays, String Manipulation, and Regular Expressions

Level up your scripting with arrays, string tricks, arithmetic, pattern matching and here documents.

~6 min Beginner

Arrays: many values in one variable

A normal variable holds one value. An array holds a list of values.

fruits=(apple banana cherry)

echo "${fruits[0]}"
echo "${fruits[@]}"
echo "${#fruits[@]}"

fruits+=(date)
fruits[1]="blueberry"
  • Items are numbered from 0. ${fruits[0]} is apple.
  • ${fruits[@]} means all items.
  • ${#fruits[@]} is the number of items, here 3.
  • +=(date) adds an item to the end.
  • fruits[1]="blueberry" replaces the second item.

Loop through an array:

for f in "${fruits[@]}"; do
    echo "Fruit: $f"
done

The quotes around "${fruits[@]}" keep items that contain spaces as single items.

Associative arrays

An associative array uses names (keys) instead of numbers. It needs Bash 4 or newer.

declare -A age
age[alex]=30
age[sam]=25
echo "Alex is ${age[alex]}"
for name in "${!age[@]}"; do
    echo "$name is ${age[$name]}"
done

${!age[@]} gives all the keys.

String tricks

Bash can handle text without calling other programs.

text="Hello, World"

echo "${#text}"
echo "${text:0:5}"
echo "${text:7}"
echo "${text^^}"
echo "${text,,}"
echo "${text/World/Bash}"
  • ${#text} is the length, 12.
  • ${text:0:5} is a slice that starts at position 0 and is 5 characters long: Hello.
  • ${text:7} starts at position 7 and goes to the end: World.
  • ${text^^} converts to uppercase and ${text,,} to lowercase.
  • ${text/World/Bash} replaces the first World with Bash.

Trimming and defaults

file="report.final.pdf"
echo "${file%.pdf}"
echo "${file##*.}"
echo "${file#*.}"
echo "${name:-guest}"
  • % removes a matching piece from the end. ${file%.pdf} gives report.final.
  • # removes a matching piece from the start. A single # removes the shortest match, and ## removes the longest.
  • ${file##*.} removes everything up to the last dot and leaves the extension, pdf.
  • ${file#*.} removes up to the first dot and leaves final.pdf.
  • ${name:-guest} uses guest when name is empty.

Arithmetic

echo $((7 + 3))
echo $((17 % 5))
x=$((x + 1))

$(( )) calculates with whole numbers. The operators are + - * / %, and % gives the remainder, so 17 % 5 is 2. Bash does not handle decimals. For decimals use a tool such as bc or awk.

Regular expressions in tests

Inside [[ ]], the =~ operator tests whether text matches a regular expression.

email="alex@example.com"
if [[ $email =~ ^[a-z]+@[a-z]+\.com$ ]]; then
    echo "Looks like an email"
fi

^ and $ mark the start and end, [a-z]+ means one or more lowercase letters, and \. is a literal dot.

Here documents

A here document feeds several lines of text into a command. Everything between the two EOF markers is the text.

cat <<EOF > report.txt
User: $USER
Date: $(date +%F)
EOF

The variables and commands inside are replaced, then the text is written to report.txt. The marker name can be any word, but EOF is the common choice, and the closing marker must be on a line by itself.

Sign up to track your progress Mark lessons as read and pick up where you left off Sign up free to unlock this practice Your first practice lesson is free to try. Create an account to unlock the rest and save your progress