Regular Expressions in Bash
A regular expression (regex) is a pattern used to match, search, or validate text. In Bash, regular expressions work with tools like grep, sed, and awk. They are extremely useful for filtering log files, validating user input, and transforming text.
What Is a Regular Expression?
┌──────────────────────────────────────────────────────┐
│ Text: "Order 1001 was shipped on 2026-04-18" │
│ │
│ Pattern: [0-9]{4} │
│ Matches: 1001, 2026, 0418 (4-digit numbers) │
│ │
│ Pattern: \d{4}-\d{2}-\d{2} │
│ Matches: 2026-04-18 (date format) │
└──────────────────────────────────────────────────────┘
Regex Special Characters
| Character | Meaning | Example |
|---|---|---|
. | Any single character | c.t matches cat, cut, cot |
* | Zero or more of the previous character | ba* matches b, ba, baa, baaa |
+ | One or more of the previous character | ba+ matches ba, baa, baaa |
? | Zero or one of the previous character | colou?r matches color or colour |
^ | Start of a line | ^Error matches lines starting with Error |
$ | End of a line | done$ matches lines ending with done |
[ ] | Character class – any one character inside | [aeiou] matches any vowel |
[^ ] | Negated class – any character NOT inside | [^0-9] matches non-digits |
{n} | Exactly n times | [0-9]{3} matches exactly 3 digits |
{n,m} | Between n and m times | [0-9]{2,4} matches 2–4 digits |
\ | Escape special character | \. matches a literal dot |
| | OR – match either side | cat|dog matches cat or dog |
( ) | Grouping | (ab)+ matches ab, abab, ababab |
Using grep with Regular Expressions
Basic grep
grep "error" server.log
grep with Extended Regex (-E flag)
grep -E "error|warning" server.log
Match Lines Starting with a Pattern
grep "^ERROR" server.log
Match Lines Ending with a Pattern
grep "failed$" server.log
Match a Phone Number Format
grep -E "^[0-9]{10}$" contacts.txt
Match an Email Address Pattern
grep -E "^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$" emails.txt
Using sed for Search and Replace
sed (stream editor) processes text line by line. The most common use is replacing text.
Replace First Occurrence Per Line
echo "I love cats and cats" | sed 's/cats/dogs/'
Output:
I love dogs and cats
Replace All Occurrences Per Line (g flag)
echo "I love cats and cats" | sed 's/cats/dogs/g'
Output:
I love dogs and dogs
Replace in a File (in-place edit with -i)
sed -i 's/localhost/192.168.1.1/g' config.txt
Delete Lines Matching a Pattern
sed '/^#/d' config.txt # Delete all comment lines
Print Only Lines Matching a Pattern (-n and p)
sed -n '/ERROR/p' server.log
Using awk for Column Processing
awk processes text line by line and splits each line into fields (columns) using a delimiter. Fields are accessed as $1, $2, etc.
┌───────────────────────────────────────────────────┐ │ Line: "Alice 88 Delhi" │ │ │ │ $1 = Alice │ │ $2 = 88 │ │ $3 = Delhi │ │ $0 = entire line │ └───────────────────────────────────────────────────┘
Print Specific Columns
echo "Alice 88 Delhi" | awk '{print $1, $3}'
Output:
Alice Delhi
Print Lines Where Column 2 is Greater Than 80
awk '$2 > 80 {print $1, "passed with score", $2}' scores.txt
Calculate Total of a Column
awk '{total += $2} END {print "Total:", total}' scores.txt
Use a Custom Delimiter
awk -F':' '{print $1}' /etc/passwd # Print all usernames
Regex in Bash [[ ]] with =~
The =~ operator inside [[ ]] tests a string against a regex pattern directly in Bash.
#!/bin/bash
phone="9876543210"
if [[ "$phone" =~ ^[0-9]{10}$ ]]; then
echo "Valid phone number"
else
echo "Invalid phone number"
fi
Output:
Valid phone number
Validate Email Format
#!/bin/bash
email="user@example.com"
if [[ "$email" =~ ^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$ ]]; then
echo "Valid email"
else
echo "Invalid email"
fi
Practical Example – Extract IP Addresses from Log
#!/bin/bash
logfile="access.log"
echo "IP addresses found in log:"
grep -oE "\b([0-9]{1,3}\.){3}[0-9]{1,3}\b" $logfile | sort | uniq
Key Takeaways
- Regular expressions define patterns to search, match, and transform text.
- Use
grep -Efor extended regex andgrep -oto print only matching parts. - Use
sed 's/old/new/g'to replace text in a stream or file. - Use
awkto process columns in structured text files. - Use
[[ "$var" =~ pattern ]]to test regex directly in Bash conditions.
