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

CharacterMeaningExample
.Any single characterc.t matches cat, cut, cot
*Zero or more of the previous characterba* matches b, ba, baa, baaa
+One or more of the previous characterba+ matches ba, baa, baaa
?Zero or one of the previous charactercolou?r matches color or colour
^Start of a line^Error matches lines starting with Error
$End of a linedone$ 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 sidecat|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 -E for extended regex and grep -o to print only matching parts.
  • Use sed 's/old/new/g' to replace text in a stream or file.
  • Use awk to process columns in structured text files.
  • Use [[ "$var" =~ pattern ]] to test regex directly in Bash conditions.

Leave a Comment