5.4. Arithmetic and String Operations#
Bash is fundamentally a string-processing language, but you often need to do math. This section covers arithmetic operations and string manipulation—essential for most scripts.
5.4.1. Quick Reference#
Task |
Syntax |
Example |
|---|---|---|
Arithmetic |
|
|
Increment |
|
|
Concatenate |
Implicit |
|
String length |
|
|
Substring |
|
|
Replace |
|
|
Case change |
|
|
Remove prefix |
|
|
Remove suffix |
|
|
5.4.2. Common Mistakes#
5.4.2.1. ❌ Treating Variables as Numbers Automatically#
# WRONG: No arithmetic happens
$ x=5
$ y=3
$ echo $x + $y
5 + 3 # Just concatenation!
# RIGHT: Use arithmetic expansion
$ echo $((x + y))
8
5.4.2.2. ❌ Spaces in Parameter Substitution#
# Works
$ echo ${var:0:3}
# Doesn't work as expected
$ echo ${ var : 0 : 3 }
# This is syntax error or wrong expansion
5.4.2.3. ❌ String Comparison with Numbers#
# WRONG: String comparison, not numeric
$ if [ "10" -lt "9" ]; then
echo "False (string comparison)"
fi
# RIGHT: Numeric comparison
$ if [ 10 -lt 9 ]; then
echo "False (numeric comparison)"
fi
5.4.2.4. ❌ Modifying Variable While Expanding#
# This doesn't do what you might expect
$ x=5
$ x=$((x + 1))
$ echo $x
6
# The expansion happens in subshell sometimes
$ (x=5; echo $((x + 1)))
6
$ echo $x
5 # Original unchanged (subshell)
5.4.3. Practical Examples#
5.4.3.1. Count Characters#
#!/bin/bash
text="The quick brown fox"
# Total characters
total=${#text}
# Count a specific character
# (using parameter substitution)
search="o"
count=${text//$search}
count=$((${#text} - ${#count}))
echo "Total characters: $total"
echo "Count of '$search': $count"
5.4.3.2. Build a Path#
#!/bin/bash
# Dynamic path construction
user="alice"
project="myapp"
version="2.1"
base="/opt"
app_dir="${base}/${user}/${project}/${version}"
echo "App directory: $app_dir"
# Create it
mkdir -p "$app_dir"
5.4.3.3. Validate and Combine Arguments#
#!/bin/bash
# Get arguments with defaults
input="${1:-input.txt}"
output="${2:-output.txt}"
# Validate lengths
if [ ${#input} -eq 0 ] || [ ${#output} -eq 0 ]; then
echo "Error: filenames required"
exit 1
fi
# Process
grep "pattern" "$input" > "$output"
5.4.3.4. Extract Parts from Filename#
#!/bin/bash
full_path="/home/alice/documents/report.2025.pdf"
# Extract components
filename="${full_path##*/}" # report.2025.pdf
directory="${full_path%/*}" # /home/alice/documents
extension="${filename##*.}" # pdf
name="${filename%.*}" # report.2025
base="${filename%%.*}" # report
echo "File: $filename"
echo "Directory: $directory"
echo "Name: $name"
echo "Extension: $extension"
echo "Base: $base"
5.4.3.5. Calculate File Size#
#!/bin/bash
# Get file size in bytes
filesize=$(stat -f%z "myfile.txt")
# Convert to MB
size_mb=$((filesize / 1048576))
echo "File size: $size_mb MB"
# Check if over limit
max_size=100
if [ $size_mb -gt $max_size ]; then
echo "File exceeds ${max_size}MB limit"
fi
5.4.3.6. Counter/Loop with Arithmetic#
#!/bin/bash
# Simple counter
count=0
for item in item1 item2 item3; do
((count++))
echo "$count. $item"
done
# Countdown
count=5
while [ $count -gt 0 ]; do
echo $count
((count--))
sleep 1
done
echo "Blast off!"
5.4.4. Substring Operations#
Already covered in section 0504:
$ text="hello"
# Characters 0-2
$ echo ${text:0:3}
hel
# From position 1 to end
$ echo ${text:1}
ello
# Last 2 characters
$ echo ${text: -2}
lo
5.4.5. Trimming Whitespace#
Remove leading/trailing spaces:
# Remove all whitespace
$ text=" hello world "
$ echo ${text}
hello world
# Quotes preserve spaces
$ echo ${text// /}
helloworld
# Remove all spaces
# Trim leading whitespace
$ echo ${text##*( )}
hello world
# Remove trailing whitespace
$ echo ${text%%*( )}
hello world
More practical approach using xargs:
$ text=" hello world "
$ echo "$text" | xargs
hello world
5.4.6. Case Conversion (Bash 4+)#
Convert strings to different cases:
# To uppercase
$ name="alice"
$ echo ${name^^}
ALICE
# To lowercase
$ NAME="ALICE"
$ echo ${NAME,,}
alice
# Capitalize first letter
$ name="alice"
$ echo ${name^}
Alice
# Lowercase first letter
$ NAME="Alice"
$ echo ${NAME,}
alice
5.4.7. String Comparison#
Compare strings (Chapter 6 covers more):
# Check if strings are equal
$ if [ "$str1" = "$str2" ]; then
echo "Same"
fi
# Check if strings are different
$ if [ "$str1" != "$str2" ]; then
echo "Different"
fi
# Check if string is empty
$ if [ -z "$str" ]; then
echo "Empty"
fi
# Check if string is not empty
$ if [ -n "$str" ]; then
echo "Not empty"
fi
5.4.8. String Length#
Get length of a string (covered briefly before):
$ text="hello world"
$ echo ${#text}
11
# Validate length
$ password="secret"
if [ ${#password} -lt 8 ]; then
echo "Password too short"
fi
5.4.9. String Concatenation#
Bash concatenation is implicit (no operator needed):
# Simply place strings next to each other
$ greeting="Hello"
$ name="Alice"
$ message="$greeting, $name!"
$ echo $message
Hello, Alice!
# Without spaces
$ file="data"
$ ext="txt"
$ filename="${file}.${ext}"
$ echo $filename
data.txt
# Concatenate with variable and literal
$ count=5
$ message="Found $count errors"
$ echo $message
Found 5 errors
5.4.10. The let Command#
An older (but still valid) way to do arithmetic:
# let is equivalent to $((...))
$ let sum=5+3
$ echo $sum
8
# Can use let for multiple operations
$ let x=5
$ let x=x+1
$ echo $x
6
# Shorthand for increment
$ let x++
But $((x + 1)) is clearer in modern bash.
5.4.11. Arithmetic: The Basics#
Remember: bash stores everything as strings. To do math, you need special syntax.
5.4.11.1. Arithmetic Expansion: $((…))#
The primary way to do math in bash:
# Basic arithmetic
$ x=5
$ y=3
$ echo $((x + y))
8
# Store result in variable
$ sum=$((x + y))
$ echo $sum
8
# Arithmetic without variables
$ echo $((10 + 5))
15
# More complex expressions
$ echo $((10 * 5 - 3))
47
# Division (integer only)
$ echo $((10 / 3))
3
# Result is integer, remainder discarded
# Modulo (remainder)
$ echo $((10 % 3))
1
5.4.11.2. Operators#
Operator |
Meaning |
Example |
|---|---|---|
|
Addition |
|
|
Subtraction |
|
|
Multiplication |
|
|
Division (integer) |
|
|
Modulo (remainder) |
|
|
Exponentiation |
|
|
Increment |
|
|
Decrement |
|
5.4.11.3. Variable Increment/Decrement#
# Pre-increment (increment, then use)
$ x=5
$ echo $((++x))
6
$ echo $x
6
# Post-increment (use, then increment)
$ x=5
$ echo $((x++))
5
$ echo $x
6
# Shortcuts
$ ((x++)) # Increment x
$ echo $x
6
$ ((y--)) # Decrement y
$ echo $y
(if y was 5, now it's 4)