How to Match Regex in Bash
• 2 min read
bash regex pattern matching regular expression =~ operator
Quick Answer: Match Regex in Bash
To match a regex pattern, use the =~ operator in Bash: [[ "$string" =~ pattern ]]. This returns true if the pattern matches anywhere in the string. Anchor with ^ for start and $ for end. The =~ operator is Bash’s native regex matching method.
Quick Comparison: Regex Matching Methods
| Method | Syntax | Speed | Best For | Complexity |
|---|---|---|---|---|
| =~ operator | [[ $var =~ regex ]] | Fastest | Bash conditionals | Simple |
| grep -E | grep -E pattern file | Medium | File content | Simple |
| sed /pattern/ | sed -n '/pattern/p' | Medium | Line filtering | Moderate |
| awk /pattern/ | awk '/pattern/' | Fast | Structured data | Moderate |
Bottom line: Use =~ for strings; use grep for files and pipes.
Use regular expressions to match patterns in bash strings. Learn using the =~ operator, test functions, and regex syntax.
Method 1: Basic Regex Matching (The Standard)
Use the =~ operator to match patterns against strings:
# Test if string matches pattern
if [[ $string =~ pattern ]]; then
echo "Match!"
fi
# Example
if [[ "hello" =~ ^h ]]; then
echo "Starts with h"
fi
When to Use Basic Pattern Matching
Use this when:
- You’re checking if a string contains a pattern
- You need simple pattern matching in conditionals
- You want the fastest Bash-native solution
- You’re validating input formats
Simple Pattern Examples
# Check if string contains substring
if [[ $text =~ "word" ]]; then
echo "Contains word"
fi
# Check if starts with
if [[ $text =~ ^start ]]; then
echo "Starts with 'start'"
fi
# Check if ends with
if [[ $text =~ end$ ]]; then
echo "Ends with 'end'"
fi
# Check if only digits
if [[ $text =~ ^[0-9]+$ ]]; then
echo "All digits"
fi
Practical Example: Email Validation
#!/bin/bash
# File: validate_email.sh
validate_email() {
local email="$1"
# Simple email pattern
if [[ $email =~ ^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$ ]]; then
return 0
else
return 1
fi
}
# Usage
emails=("user@example.com" "invalid@" "test@domain.co.uk" "no-at-sign.com")
for email in "${emails[@]}"; do
if validate_email "$email"; then
echo "✓ Valid: $email"
else
echo "✗ Invalid: $email"
fi
done
Output:
✓ Valid: user@example.com
✗ Invalid: invalid@
✓ Valid: test@domain.co.uk
✗ Invalid: no-at-sign.com
Capture Groups
#!/bin/bash
# Use capture groups with BASH_REMATCH
text="User: John, Age: 30"
if [[ $text =~ User:\ ([a-zA-Z]+),\ Age:\ ([0-9]+) ]]; then
name="${BASH_REMATCH[1]}"
age="${BASH_REMATCH[2]}"
echo "Name: $name"
echo "Age: $age"
fi
Output:
Name: John
Age: 30
Practical Example: Log Parser
#!/bin/bash
# File: parse_log_line.sh
log_line="2026-02-21 14:30:45 ERROR Connection refused from 192.168.1.1"
# Parse log format
if [[ $log_line =~ ^([0-9-]+)\ ([0-9:]+)\ ([A-Z]+)\ (.*)\ from\ ([0-9.]+)$ ]]; then
date="${BASH_REMATCH[1]}"
time="${BASH_REMATCH[2]}"
level="${BASH_REMATCH[3]}"
message="${BASH_REMATCH[4]}"
ip="${BASH_REMATCH[5]}"
echo "Date: $date"
echo "Time: $time"
echo "Level: $level"
echo "Message: $message"
echo "IP: $ip"
fi
URL Validation
#!/bin/bash
# Validate URL format
url="$1"
if [[ $url =~ ^https?://[a-zA-Z0-9.-]+\.[a-zA-Z]{2,} ]]; then
echo "✓ Valid URL: $url"
else
echo "✗ Invalid URL: $url"
fi
IP Address Matching
#!/bin/bash
# Validate IP address (IPv4)
validate_ip() {
local ip="$1"
# Pattern for IPv4: 0-255.0-255.0-255.0-255
if [[ $ip =~ ^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$ ]]; then
# Check ranges (simple check, not perfect)
return 0
else
return 1
fi
}
if validate_ip "192.168.1.1"; then
echo "Valid IP"
fi
Case-Insensitive Matching
# Use shopt nocasematch
shopt -s nocasematch
if [[ "HELLO" =~ hello ]]; then
echo "Match (case-insensitive)"
fi
shopt -u nocasematch # Turn off
NOT Matching
# Check if does NOT match
if [[ ! $text =~ pattern ]]; then
echo "Does not match"
fi
# Example
if [[ ! "hello" =~ ^[0-9] ]]; then
echo "Doesn't start with digit"
fi
Multiple Patterns
#!/bin/bash
# Check multiple patterns
text="$1"
if [[ $text =~ ^(error|warning|info) ]]; then
level="${BASH_REMATCH[1]}"
echo "Log level: $level"
fi
Password Strength Check
#!/bin/bash
# Validate password strength
validate_password() {
local pass="$1"
# At least 8 chars, contains uppercase, lowercase, digit, special
if [[ ${#pass} -ge 8 ]] && \
[[ $pass =~ [A-Z] ]] && \
[[ $pass =~ [a-z] ]] && \
[[ $pass =~ [0-9] ]] && \
[[ $pass =~ [^a-zA-Z0-9] ]]; then
return 0
else
return 1
fi
}
if validate_password "MyPass123!"; then
echo "✓ Strong password"
else
echo "✗ Weak password"
fi
Extract Numbers from String
#!/bin/bash
text="Price: $19.99 Quantity: 5 Discount: 10%"
if [[ $text =~ \$([0-9.]+) ]]; then
price="${BASH_REMATCH[1]}"
echo "Price: $price"
fi
if [[ $text =~ Quantity:\ ([0-9]+) ]]; then
quantity="${BASH_REMATCH[1]}"
echo "Quantity: $quantity"
fi
Output:
Price: 19.99
Quantity: 5
Practical Example: Filename Pattern
#!/bin/bash
# Check if filename matches pattern
filename="report_2026_02_21.pdf"
if [[ $filename =~ ^([a-z_]+)_([0-9]{4})_([0-9]{2})_([0-9]{2})\.[a-z]+$ ]]; then
name="${BASH_REMATCH[1]}"
year="${BASH_REMATCH[2]}"
month="${BASH_REMATCH[3]}"
day="${BASH_REMATCH[4]}"
echo "Name: $name"
echo "Date: $year-$month-$day"
fi
Output:
Name: report
Date: 2026-02-21
Common Regex Patterns
# Digits only
[0-9]+
# Letters only
[a-zA-Z]+
# Alphanumeric
[a-zA-Z0-9]+
# Email-like
[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+
# IP address
[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}
# URL
https?://[a-zA-Z0-9.-]+
# Phone number
[0-9]{3}-[0-9]{3}-[0-9]{4}
# Hex color
#[0-9a-fA-F]{6}
# Start/end
^ start, $ end
Error Checking
#!/bin/bash
text="$1"
if [[ -z $text ]]; then
echo "ERROR: No text provided"
exit 1
fi
if [[ $text =~ ^[a-z]+$ ]]; then
echo "Matches pattern: lowercase letters only"
else
echo "Does not match pattern"
fi
Common Mistakes
- Missing [[ ]] double brackets - regex only works with
[[]], not[] - Not escaping special characters - use
\for.,*, etc. - Forgetting space escaping -
\for literal space - BASH_REMATCH indexing - [0] is full match, [1] is first group
- Not quoting variables - can break pattern matching
Performance Tips
- Test patterns on sample data first
- Use anchors
^and$for exact matches - Avoid complex nested patterns
- Cache pattern matches in variables
Key Points
- Use
[[ $var =~ pattern ]]for matching - Use
BASH_REMATCHfor capture groups - Escape special regex characters
- Test patterns thoroughly
- Remember double brackets required
Summary
Regular expression matching in bash uses the =~ operator with extended regex. Always use double brackets, handle capture groups properly, and test patterns thoroughly before using in production.