kavklaw@llm $ cat regex-cheatsheet.md
Metacharacters, quantifiers, groups, lookarounds, and battle-tested patterns.
. Any character except newline
\d Digit [0-9]
\D Non-digit [^0-9]
\w Word character [a-zA-Z0-9_]
\W Non-word character [^a-zA-Z0-9_]
\s Whitespace [ \t\n\r\f\v]
\S Non-whitespace
\b Word boundary
\B Non-word boundary
\\ Literal backslash
\. Literal dot
\n Newline
\t Tab
\r Carriage return
^ Start of string (or line in multiline mode)
$ End of string (or line in multiline mode)
\A Start of string (never affected by multiline)
\Z End of string (never affected by multiline)
\b Word boundary (between \w and \W)
\B Non-word boundary
Examples:
^admin String starts with "admin"
admin$ String ends with "admin"
^admin$ String is exactly "admin"
\bword\b Match "word" as a whole word
* 0 or more (greedy)
+ 1 or more (greedy)
? 0 or 1 (optional)
{n} Exactly n times
{n,} n or more times
{n,m} Between n and m times
# Greedy vs Lazy (non-greedy)
*? 0 or more (lazy — match as few as possible)
+? 1 or more (lazy)
?? 0 or 1 (lazy)
{n,m}? Between n and m (lazy)
Examples:
a.*b Greedy: "aXXXbYYYb" → matches "aXXXbYYYb"
a.*?b Lazy: "aXXXbYYYb" → matches "aXXXb"
colou?r Matches "color" and "colour"
\d{3} Exactly 3 digits
\d{2,4} 2 to 4 digits
[abc] Match a, b, or c
[^abc] Match anything except a, b, or c
[a-z] Lowercase letter
[A-Z] Uppercase letter
[0-9] Digit (same as \d)
[a-zA-Z] Any letter
[a-zA-Z0-9] Alphanumeric (same as \w minus underscore)
[^a-z] Not a lowercase letter
[-] Literal hyphen (at start or end of class)
[.] Literal dot (inside class, most special chars are literal)
# POSIX classes (used in grep, sed, awk):
[:alpha:] Letters [[:alpha:]]
[:digit:] Digits [[:digit:]]
[:alnum:] Alphanumeric [[:alnum:]]
[:upper:] Uppercase [[:upper:]]
[:lower:] Lowercase [[:lower:]]
[:space:] Whitespace [[:space:]]
[:punct:] Punctuation [[:punct:]]
[:xdigit:] Hex digits [[:xdigit:]]
(abc) Capturing group — matches "abc", stores in \1
(?:abc) Non-capturing group — matches "abc", no capture
(?P<name>abc) Named group — access by name (Python)
(?'name'abc) Named group (.NET/PCRE)
a|b Alternation — match "a" or "b"
(a|b)c Match "ac" or "bc"
# Backreferences
\1 Reference to group 1
\2 Reference to group 2
(?P=name) Reference to named group (Python)
Examples:
(ha)+ Match "ha", "haha", "hahaha"...
(\w+)\s\1 Match repeated words: "the the", "is is"
(cat|dog) Match "cat" or "dog"
# Lookahead (peek ahead without consuming)
(?=abc) Positive lookahead — next chars ARE "abc"
(?!abc) Negative lookahead — next chars are NOT "abc"
# Lookbehind (peek behind without consuming)
(?<=abc) Positive lookbehind — preceding chars ARE "abc"
(?<!abc) Negative lookbehind — preceding chars are NOT "abc"
Examples:
\d+(?= dollars) Match digits followed by " dollars" (don't capture " dollars")
"100 dollars" → captures "100"
(?<=\$)\d+ Match digits preceded by "$"
"$50" → captures "50"
\b\w+(?!ing\b) Match words NOT ending in "ing"
(?<!un)happy Match "happy" NOT preceded by "un"
# Password validation (all of these at once):
^(?=.*[A-Z])(?=.*[a-z])(?=.*\d)(?=.*[@$!%*?&]).{8,}$
│ │ │ │ │
│ │ │ │ └─ At least 8 chars
│ │ │ └─ Has special char
│ │ └─ Has digit
│ └─ Has lowercase
└─ Has uppercase
Flag Name Effect
──── ──── ──────
i Case-insensitive /admin/i matches "Admin", "ADMIN"
g Global Match all occurrences (not just first)
m Multiline ^ and $ match line boundaries
s Dotall/SingleLine . matches newline too
x Verbose/Extended Allow whitespace and comments in regex
u Unicode Full Unicode matching
# Python inline flags:
(?i)admin Case-insensitive
(?m)^line Multiline
(?s).* Dotall
# In Python code:
import re
re.search(r"admin", text, re.IGNORECASE | re.MULTILINE)
# IPv4 (simple — matches invalid IPs like 999.999.999.999)
\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}
# IPv4 (strict — 0-255 per octet)
\b(?:(?:25[0-5]|2[0-4]\d|[01]?\d\d?)\.){3}(?:25[0-5]|2[0-4]\d|[01]?\d\d?)\b
# IPv4 with CIDR
\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}/\d{1,2}
# IPv6 (simplified)
(?:[0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}
# Extract IPs from text:
grep -oP '\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}' file.txt
# Basic email
[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}
# RFC 5322 (simplified but more accurate)
(?:[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*|"(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21\x23-\x5b\x5d-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])*")@(?:(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?)
# URL (HTTP/HTTPS)
https?://[^\s/$.?#].[^\s]*
# More precise URL
https?://(?:www\.)?[-a-zA-Z0-9@:%._+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b(?:[-a-zA-Z0-9()@:%_+.~#?&/=]*)
# Domain name
(?:[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?\.)+[a-zA-Z]{2,}
# Extract domains from text:
grep -oP '(?:[a-zA-Z0-9-]+\.)+[a-zA-Z]{2,}' file.txt
# MAC address
(?:[0-9a-fA-F]{2}[:-]){5}[0-9a-fA-F]{2}
# Credit card (basic)
\b\d{4}[- ]?\d{4}[- ]?\d{4}[- ]?\d{4}\b
# Phone number (US)
(?:\+?1[-.\s]?)?(?:\(?\d{3}\)?[-.\s]?)?\d{3}[-.\s]?\d{4}
# Social Security Number
\b\d{3}-\d{2}-\d{4}\b
# Hash patterns
[a-fA-F0-9]{32} MD5
[a-fA-F0-9]{40} SHA-1
[a-fA-F0-9]{64} SHA-256
# Base64 string
[A-Za-z0-9+/]{4,}={0,2}
# JWT token
eyJ[A-Za-z0-9_-]*\.eyJ[A-Za-z0-9_-]*\.[A-Za-z0-9_-]*
# Windows file path
[a-zA-Z]:\\(?:[^\\\/:*?"<>|\r\n]+\\)*[^\\\/:*?"<>|\r\n]*
# Linux file path
(?:/[^\s/]+)+
# Basic regex (BRE) — default grep
grep "pattern" file # Basic regex
grep -i "pattern" file # Case insensitive
grep -n "pattern" file # Show line numbers
grep -c "pattern" file # Count matches
grep -v "pattern" file # Invert (non-matching)
grep -o "pattern" file # Only matching part
grep -r "pattern" dir/ # Recursive
# Extended regex (ERE) — use -E or egrep
grep -E "(cat|dog)" file # Alternation
grep -E "\d+" file # One or more digits
grep -E "^(#|$)" file # Comments or empty lines
# Perl regex (PCRE) — use -P
grep -P "\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}" file # IP addresses
grep -P "(?<=password=)\S+" file # Lookbehind — text after "password="
grep -oP '(?<=href=")[^"]+' file # Extract URLs from href
# BRE vs ERE differences:
# BRE: \( \) \{ \} \| need backslashes
# ERE: ( ) { } | work without backslashes
grep "ab\(cd\)\+" file # BRE: group + repetition
grep -E "ab(cd)+" file # ERE: same thing, cleaner
# sed uses BRE by default, -E for ERE
# Basic substitution
sed 's/old/new/' file # First match per line
sed 's/old/new/g' file # All matches
sed 's/old/new/gi' file # All matches, case-insensitive
# Using groups
sed 's/\(.*\)@\(.*\)/User: \1, Domain: \2/' emails.txt
sed -E 's/(.*)@(.*)/User: \1, Domain: \2/' emails.txt # ERE version
# Delete lines matching pattern
sed '/^#/d' file # Delete comment lines
sed '/^$/d' file # Delete empty lines
# Print only matching lines
sed -n '/pattern/p' file # Like grep
# Replace IP addresses
sed -E 's/[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}/REDACTED/g' file
# Extract between delimiters
sed -n 's/.*password="\([^"]*\)".*/\1/p' file
# awk uses ERE natively (no -E needed)
# Match lines containing pattern
awk '/pattern/' file # Print matching lines
awk '/^root/' /etc/passwd # Lines starting with "root"
awk '!/^#/' file # Lines NOT starting with #
# Match specific field
awk -F: '$1 ~ /admin/' /etc/passwd # Field 1 matches "admin"
awk -F: '$1 !~ /nologin/' /etc/passwd # Field 1 doesn't match
# Substitute
awk '{gsub(/old/, "new"); print}' file # Global substitution
awk '{sub(/first/, "replaced"); print}' file # First match only
# Extract with regex
awk 'match($0, /[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+/) {print substr($0, RSTART, RLENGTH)}' file
import re
text = "Call 123-456-7890 or 987-654-3210"
# Search (first match)
m = re.search(r"\d{3}-\d{3}-\d{4}", text)
if m:
print(m.group()) # 123-456-7890
print(m.start()) # Position 5
# Find all matches
phones = re.findall(r"\d{3}-\d{3}-\d{4}", text)
# ['123-456-7890', '987-654-3210']
# Find all with groups
pairs = re.findall(r"(\d{3})-(\d{3})-(\d{4})", text)
# [('123', '456', '7890'), ('987', '654', '3210')]
# Substitution
clean = re.sub(r"\d{3}-\d{3}-\d{4}", "REDACTED", text)
# Split
parts = re.split(r"[,;\s]+", "one, two; three four")
# Compile (reuse pattern)
pattern = re.compile(r"\b\w+@\w+\.\w+\b", re.IGNORECASE)
emails = pattern.findall(text)
# Named groups
m = re.search(r"(?P<area>\d{3})-(?P<num>\d{3}-\d{4})", text)
if m:
print(m.group("area")) # 123
# Test regex from command line:
echo "test 192.168.1.1 string" | grep -oP '\d+\.\d+\.\d+\.\d+'
# Python one-liner:
python3 -c "import re; print(re.findall(r'\d+\.\d+\.\d+\.\d+', 'IP is 10.10.10.5'))"
# Online testers:
# regex101.com — best for testing with explanation
# regexr.com — visual regex tester
# debuggex.com — railroad diagram visualization