Back to Skills
    🦞

    regex-patterns

    Practical regex patterns across languages and use

    By @gitgoodordietrying
    View on GitHub
    SKILL.md
    ---
    name: regex-patterns
    description: Practical regex patterns across languages and use cases. Use when validating input (email, URL, IP), parsing log lines, extracting data from text, refactoring code with search-and-replace, or debugging why a regex doesn't match.
    metadata: {"clawdbot":{"emoji":"🔤","requires":{"anyBins":["grep","python3","node"]},"os":["linux","darwin","win32"]}}
    ---
    
    # Regex Patterns
    
    Practical regular expression cookbook. Patterns for validation, parsing, extraction, and refactoring across JavaScript, Python, Go, and command-line tools.
    
    ## When to Use
    
    - Validating user input (email, URL, IP, phone, dates)
    - Parsing log lines or structured text
    - Extracting data from strings (IDs, numbers, tokens)
    - Search-and-replace in code (rename variables, update imports)
    - Filtering lines in files or command output
    - Debugging regexes that don't match as expected
    
    ## Quick Reference
    
    ### Metacharacters
    
    | Pattern | Matches | Example |
    |---|---|---|
    | `.` | Any character (except newline) | `a.c` matches `abc`, `a1c` |
    | `\d` | Digit `[0-9]` | `\d{3}` matches `123` |
    | `\w` | Word char `[a-zA-Z0-9_]` | `\w+` matches `hello_123` |
    | `\s` | Whitespace `[ \t\n\r\f]` | `\s+` matches spaces/tabs |
    | `\b` | Word boundary | `\bcat\b` matches `cat` not `scatter` |
    | `^` | Start of line | `^Error` matches line starting with Error |
    | `
    
      
        
        
        
        OpenClaw Resources Directory – Skills, Tools, Plugins & Guides | The Claw Guy
        
        
        
        
        
        
        
        
    
        
        
        
        
    
        
        
        
        
        
      
      
    
    
      
         | End of line | `\.js
    
      
        
        
        
        OpenClaw Resources Directory – Skills, Tools, Plugins & Guides | The Claw Guy
        
        
        
        
        
        
        
        
    
        
        
        
        
    
        
        
        
        
        
      
      
    
    
      
         matches line ending with .js |
    | `\D`, `\W`, `\S` | Negated: non-digit, non-word, non-space | |
    
    ### Quantifiers
    
    | Pattern | Meaning |
    |---|---|
    | `*` | 0 or more (greedy) |
    | `+` | 1 or more (greedy) |
    | `?` | 0 or 1 (optional) |
    | `{3}` | Exactly 3 |
    | `{2,5}` | Between 2 and 5 |
    | `{3,}` | 3 or more |
    | `*?`, `+?` | Lazy (match as few as possible) |
    
    ### Groups and Alternation
    
    | Pattern | Meaning |
    |---|---|
    | `(abc)` | Capture group |
    | `(?:abc)` | Non-capturing group |
    | `(?P<name>abc)` | Named group (Python) |
    | `(?<name>abc)` | Named group (JS/Go) |
    | `a\|b` | Alternation (a or b) |
    | `[abc]` | Character class (a, b, or c) |
    | `[^abc]` | Negated class (not a, b, or c) |
    | `[a-z]` | Range |
    
    ### Lookahead and Lookbehind
    
    | Pattern | Meaning |
    |---|---|
    | `(?=abc)` | Positive lookahead (followed by abc) |
    | `(?!abc)` | Negative lookahead (not followed by abc) |
    | `(?<=abc)` | Positive lookbehind (preceded by abc) |
    | `(?<!abc)` | Negative lookbehind (not preceded by abc) |
    
    ## Validation Patterns
    
    ### Email
    
    ```
    # Basic (covers 99% of real emails)
    ^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$
    
    # Stricter (no consecutive dots, no leading/trailing dots in local part)
    ^[a-zA-Z0-9]([a-zA-Z0-9._%+-]*[a-zA-Z0-9])?@[a-zA-Z0-9]([a-zA-Z0-9-]*[a-zA-Z0-9])?(\.[a-zA-Z]{2,})+$
    ```
    
    ### URL
    
    ```
    # HTTP/HTTPS URLs
    https?://[a-zA-Z0-9]([a-zA-Z0-9-]*[a-zA-Z0-9])?(\.[a-zA-Z0-9]([a-zA-Z0-9-]*[a-zA-Z0-9])?)*(/[^\s]*)?
    
    # With optional port and query
    https?://[^\s/]+(/[^\s?]*)?(\?[^\s#]*)?(#[^\s]*)?
    ```
    
    ### IP Addresses
    
    ```
    # IPv4
    \b(?:(?:25[0-5]|2[0-4]\d|[01]?\d\d?)\.){3}(?:25[0-5]|2[0-4]\d|[01]?\d\d?)\b
    
    # IPv4 (simple, allows invalid like 999.999.999.999)
    \b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\b
    
    # IPv6 (simplified)
    (?:[0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}
    ```
    
    ### Phone Numbers
    
    ```
    # US phone (various formats)
    (?:\+1[-.\s]?)?\(?\d{3}\)?[-.\s]?\d{3}[-.\s]?\d{4}
    # Matches: +1 (555) 123-4567, 555.123.4567, 5551234567
    
    # International (E.164)
    \+[1-9]\d{6,14}
    ```
    
    ### Dates and Times
    
    ```
    # ISO 8601 date
    \d{4}-(?:0[1-9]|1[0-2])-(?:0[1-9]|[12]\d|3[01])
    
    # ISO 8601 datetime
    \d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d+)?(?:Z|[+-]\d{2}:\d{2})
    
    # US date (MM/DD/YYYY)
    (?:0[1-9]|1[0-2])/(?:0[1-9]|[12]\d|3[01])/\d{4}
    
    # Time (HH:MM:SS, 24h)
    (?:[01]\d|2[0-3]):[0-5]\d:[0-5]\d
    ```
    
    ### Passwords (Strength Check)
    
    ```
    # At least 8 chars, 1 upper, 1 lower, 1 digit, 1 special
    ^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[!@#$%^&*()_+=-]).{8,}$
    ```
    
    ### UUIDs
    
    ```
    [0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}
    ```
    
    ### Semantic Version
    
    ```
    \bv?(\d+)\.(\d+)\.(\d+)(?:-([\w.]+))?(?:\+([\w.]+))?\b
    # Captures: major, minor, patch, prerelease, build
    # Matches: 1.2.3, v1.0.0-beta.1, 2.0.0+build.123
    ```
    
    ## Parsing Patterns
    
    ### Log Lines
    
    ```bash
    # Apache/Nginx access log
    # Format: IP - - [date] "METHOD /path HTTP/x.x" status size
    grep -oP '(\S+) - - \[([^\]]+)\] "(\w+) (\S+) \S+" (\d+) (\d+)' access.log
    
    # Extract IP and status code
    grep -oP '^\S+|"\s\K\d{3}' access.log
    
    # Syslog format
    # Format: Mon DD HH:MM:SS hostname process[pid]: message
    grep -oP '^\w+\s+\d+\s[\d:]+\s(\S+)\s(\S+)\[(\d+)\]:\s(.*)' syslog
    
    # JSON log — extract a field
    grep -oP '"level"\s*:\s*"\K[^"]+' app.log
    grep -oP '"message"\s*:\s*"\K[^"]+' app.log
    ```
    
    ### Code Patterns
    
    ```bash
    # Find function definitions (JavaScript/TypeScript)
    grep -nP '(?:function\s+\w+|(?:const|let|var)\s+\w+\s*=\s*(?:async\s*)?\([^)]*\)\s*=>|(?:async\s+)?function\s*\()' src/*.ts
    
    # Find class definitions
    grep -nP 'class\s+\w+(?:\s+extends\s+\w+)?' src/*.ts
    
    # Find import statements
    grep -nP '^import\s+.*\s+from\s+' src/*.ts
    
    # Find TODO/FIXME/HACK comments
    grep -rnP '(?:TODO|FIXME|HACK|XXX|WARN)(?:\([^)]+\))?:?\s+' src/
    
    # Find console.log left in code
    grep -rnP 'console\.(log|debug|info|warn|error)\(' src/ --include='*.ts' --include='*.js'
    ```
    
    ### Data Extraction
    
    ```bash
    # Extract all email addresses from a file
    grep -oP '[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}' file.txt
    
    # Extract all URLs
    grep -oP 'https?://[^\s<>"]+' file.html
    
    # Extract all quoted strings
    grep -oP '"[^"\\]*(?:\\.[^"\\]*)*"' file.json
    
    # Extract numbers (integer and decimal)
    grep -oP '-?\d+\.?\d*' data.txt
    
    # Extract key-value pairs (key=value)
    grep -oP '\b(\w+)=([^\s&]+)' query.txt
    
    # Extract hashtags
    grep -oP '#\w+' posts.txt
    
    # Extract hex colors
    grep -oP '#[0-9a-fA-F]{3,8}\b' styles.css
    ```
    
    ## Language-Specific Usage
    
    ### JavaScript
    
    ```javascript
    // Test if a string matches
    const emailRegex = /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/;
    emailRegex.test('user@example.com'); // true
    
    // Extract with capture groups
    const match = '2026-02-03T12:30:00Z'.match(/(\d{4})-(\d{2})-(\d{2})/);
    // match[1] = '2026', match[2] = '02', match[3] = '03'
    
    // Named groups
    const m = 'John Doe, age 30'.match(/(?<name>[A-Za-z ]+), age (?<age>\d+)/);
    // m.groups.name = 'John Doe', m.groups.age = '30'
    
    // Find all matches (matchAll returns iterator)
    const text = 'Call 555-1234 or 555-5678';
    const matches = [...text.matchAll(/\d{3}-\d{4}/g)];
    // [{0: '555-1234', index: 5}, {0: '555-5678', index: 18}]
    
    // Replace with callback
    'hello world'.replace(/\b\w/g, c => c.toUpperCase());
    // 'Hello World'
    
    // Replace with named groups
    '2026-02-03'.replace(/(?<y>\d{4})-(?<m>\d{2})-(?<d>\d{2})/, '
    lt;m>/
    lt;d>/
    lt;y>'); // '02/03/2026' // Split with regex 'one, two; three'.split(/[,;]\s*/); // ['one', 'two', 'three'] ``` ### Python ```python import re # Match (anchored to start) m = re.match(r'^(\w+)@(\w+)\.(\w+)
    #x27;, 'user@example.com') if m: print(m.group(1)) # 'user' # Search (find first match anywhere) m = re.search(r'\d{3}-\d{4}', 'Call 555-1234 today') print(m.group()) # '555-1234' # Find all matches emails = re.findall(r'[\w.+-]+@[\w.-]+\.\w{2,}', text) # Named groups m = re.match(r'(?P<name>\w+)\s+(?P<age>\d+)', 'Alice 30') print(m.group('name')) # 'Alice' # Substitution result = re.sub(r'\bfoo\b', 'bar', 'foo foobar foo') # 'bar foobar bar' # Sub with callback result = re.sub(r'\b\w', lambda m: m.group().upper(), 'hello world') # 'Hello World' # Compile for reuse (faster in loops) pattern = re.compile(r'\d{4}-\d{2}-\d{2}') dates = pattern.findall(log_text) # Multiline and DOTALL re.findall(r'^ERROR.*
    #x27;, text, re.MULTILINE) # ^ and $ match line boundaries re.search(r'start.*end', text, re.DOTALL) # . matches newlines # Verbose mode (readable complex patterns) pattern = re.compile(r''' ^ # Start of string (?P<year>\d{4}) # Year -(?P<month>\d{2}) # Month -(?P<day>\d{2}) # Day $ # End of string ''', re.VERBOSE) ``` ### Go ```go import "regexp" // Compile pattern (panics on invalid regex) re := regexp.MustCompile(`\d{4}-\d{2}-\d{2}`) // Match test re.MatchString("2026-02-03") // true // Find first match re.FindString("Date: 2026-02-03 and 2026-03-01") // "2026-02-03" // Find all matches re.FindAllString(text, -1) // []string of all matches // Capture groups re := regexp.MustCompile(`(\w+)@(\w+)\.(\w+)`) match := re.FindStringSubmatch("user@example.com") // match[0] = "user@example.com", match[1] = "user", match[2] = "example" // Named groups re := regexp.MustCompile(`(?P<year>\d{4})-(?P<month>\d{2})-(?P<day>\d{2})`) match := re.FindStringSubmatch("2026-02-03") for i, name := range re.SubexpNames() { if name != "" { fmt.Printf("%s: %s\n", name, match[i]) } } // Replace re.ReplaceAllString("foo123bar", "NUM") // "fooNUMbar" // Replace with function re.ReplaceAllStringFunc(text, strings.ToUpper) // Note: Go uses RE2 syntax — no lookahead/lookbehind ``` ### Command Line (grep/sed) ```bash # grep -P uses PCRE (Perl-compatible — full features) # grep -E uses Extended regex (no lookahead/lookbehind) # Find lines matching a pattern grep -P '\d{3}-\d{4}' file.txt # Extract only the matching part grep -oP '\d{3}-\d{4}' file.txt # Invert match (lines NOT matching) grep -vP 'DEBUG|TRACE' app.log # sed replacement sed 's/oldPattern/newText/g' file.txt # Basic sed -E 's/foo_([a-z]+)/bar_\1/g' file.txt # Extended with capture group # Perl one-liner (most powerful) perl -pe 's/(?<=price:\s)\d+/0/g' file.txt # Lookbehind works in Perl ``` ## Search-and-Replace Patterns ### Code Refactoring ```bash # Rename a variable across files grep -rlP '\boldName\b' src/ | xargs sed -i 's/\boldName\b/newName/g' # Convert var to const (JavaScript) sed -i -E 's/\bvar\b/const/g' src/*.js # Convert single quotes to double quotes sed -i "s/'/\"/g" src/*.ts # Add trailing commas to object properties sed -i -E 's/^(\s+\w+:.+[^,])$/\1,/' config.json # U ... (truncated)
    | End of line | `\\.js OpenClaw Resources Directory – Skills, Tools, Plugins & Guides | The Claw Guy matches line ending with .js |\n| `\\D`, `\\W`, `\\S` | Negated: non-digit, non-word, non-space | |\n\n### Quantifiers\n\n| Pattern | Meaning |\n|---|---|\n| `*` | 0 or more (greedy) |\n| `+` | 1 or more (greedy) |\n| `?` | 0 or 1 (optional) |\n| `{3}` | Exactly 3 |\n| `{2,5}` | Between 2 and 5 |\n| `{3,}` | 3 or more |\n| `*?`, `+?` | Lazy (match as few as possible) |\n\n### Groups and Alternation\n\n| Pattern | Meaning |\n|---|---|\n| `(abc)` | Capture group |\n| `(?:abc)` | Non-capturing group |\n| `(?P\u003cname>abc)` | Named group (Python) |\n| `(?\u003cname>abc)` | Named group (JS/Go) |\n| `a\\|b` | Alternation (a or b) |\n| `[abc]` | Character class (a, b, or c) |\n| `[^abc]` | Negated class (not a, b, or c) |\n| `[a-z]` | Range |\n\n### Lookahead and Lookbehind\n\n| Pattern | Meaning |\n|---|---|\n| `(?=abc)` | Positive lookahead (followed by abc) |\n| `(?!abc)` | Negative lookahead (not followed by abc) |\n| `(?\u003c=abc)` | Positive lookbehind (preceded by abc) |\n| `(?\u003c!abc)` | Negative lookbehind (not preceded by abc) |\n\n## Validation Patterns\n\n### Email\n\n```\n# Basic (covers 99% of real emails)\n^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$\n\n# Stricter (no consecutive dots, no leading/trailing dots in local part)\n^[a-zA-Z0-9]([a-zA-Z0-9._%+-]*[a-zA-Z0-9])?@[a-zA-Z0-9]([a-zA-Z0-9-]*[a-zA-Z0-9])?(\\.[a-zA-Z]{2,})+$\n```\n\n### URL\n\n```\n# HTTP/HTTPS URLs\nhttps?://[a-zA-Z0-9]([a-zA-Z0-9-]*[a-zA-Z0-9])?(\\.[a-zA-Z0-9]([a-zA-Z0-9-]*[a-zA-Z0-9])?)*(/[^\\s]*)?\n\n# With optional port and query\nhttps?://[^\\s/]+(/[^\\s?]*)?(\\?[^\\s#]*)?(#[^\\s]*)?\n```\n\n### IP Addresses\n\n```\n# IPv4\n\\b(?:(?:25[0-5]|2[0-4]\\d|[01]?\\d\\d?)\\.){3}(?:25[0-5]|2[0-4]\\d|[01]?\\d\\d?)\\b\n\n# IPv4 (simple, allows invalid like 999.999.999.999)\n\\b\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\b\n\n# IPv6 (simplified)\n(?:[0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}\n```\n\n### Phone Numbers\n\n```\n# US phone (various formats)\n(?:\\+1[-.\\s]?)?\\(?\\d{3}\\)?[-.\\s]?\\d{3}[-.\\s]?\\d{4}\n# Matches: +1 (555) 123-4567, 555.123.4567, 5551234567\n\n# International (E.164)\n\\+[1-9]\\d{6,14}\n```\n\n### Dates and Times\n\n```\n# ISO 8601 date\n\\d{4}-(?:0[1-9]|1[0-2])-(?:0[1-9]|[12]\\d|3[01])\n\n# ISO 8601 datetime\n\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}(?:\\.\\d+)?(?:Z|[+-]\\d{2}:\\d{2})\n\n# US date (MM/DD/YYYY)\n(?:0[1-9]|1[0-2])/(?:0[1-9]|[12]\\d|3[01])/\\d{4}\n\n# Time (HH:MM:SS, 24h)\n(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d\n```\n\n### Passwords (Strength Check)\n\n```\n# At least 8 chars, 1 upper, 1 lower, 1 digit, 1 special\n^(?=.*[a-z])(?=.*[A-Z])(?=.*\\d)(?=.*[!@#$%^&*()_+=-]).{8,}$\n```\n\n### UUIDs\n\n```\n[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}\n```\n\n### Semantic Version\n\n```\n\\bv?(\\d+)\\.(\\d+)\\.(\\d+)(?:-([\\w.]+))?(?:\\+([\\w.]+))?\\b\n# Captures: major, minor, patch, prerelease, build\n# Matches: 1.2.3, v1.0.0-beta.1, 2.0.0+build.123\n```\n\n## Parsing Patterns\n\n### Log Lines\n\n```bash\n# Apache/Nginx access log\n# Format: IP - - [date] \"METHOD /path HTTP/x.x\" status size\ngrep -oP '(\\S+) - - \\[([^\\]]+)\\] \"(\\w+) (\\S+) \\S+\" (\\d+) (\\d+)' access.log\n\n# Extract IP and status code\ngrep -oP '^\\S+|\"\\s\\K\\d{3}' access.log\n\n# Syslog format\n# Format: Mon DD HH:MM:SS hostname process[pid]: message\ngrep -oP '^\\w+\\s+\\d+\\s[\\d:]+\\s(\\S+)\\s(\\S+)\\[(\\d+)\\]:\\s(.*)' syslog\n\n# JSON log — extract a field\ngrep -oP '\"level\"\\s*:\\s*\"\\K[^\"]+' app.log\ngrep -oP '\"message\"\\s*:\\s*\"\\K[^\"]+' app.log\n```\n\n### Code Patterns\n\n```bash\n# Find function definitions (JavaScript/TypeScript)\ngrep -nP '(?:function\\s+\\w+|(?:const|let|var)\\s+\\w+\\s*=\\s*(?:async\\s*)?\\([^)]*\\)\\s*=>|(?:async\\s+)?function\\s*\\()' src/*.ts\n\n# Find class definitions\ngrep -nP 'class\\s+\\w+(?:\\s+extends\\s+\\w+)?' src/*.ts\n\n# Find import statements\ngrep -nP '^import\\s+.*\\s+from\\s+' src/*.ts\n\n# Find TODO/FIXME/HACK comments\ngrep -rnP '(?:TODO|FIXME|HACK|XXX|WARN)(?:\\([^)]+\\))?:?\\s+' src/\n\n# Find console.log left in code\ngrep -rnP 'console\\.(log|debug|info|warn|error)\\(' src/ --include='*.ts' --include='*.js'\n```\n\n### Data Extraction\n\n```bash\n# Extract all email addresses from a file\ngrep -oP '[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}' file.txt\n\n# Extract all URLs\ngrep -oP 'https?://[^\\s\u003c>\"]+' file.html\n\n# Extract all quoted strings\ngrep -oP '\"[^\"\\\\]*(?:\\\\.[^\"\\\\]*)*\"' file.json\n\n# Extract numbers (integer and decimal)\ngrep -oP '-?\\d+\\.?\\d*' data.txt\n\n# Extract key-value pairs (key=value)\ngrep -oP '\\b(\\w+)=([^\\s&]+)' query.txt\n\n# Extract hashtags\ngrep -oP '#\\w+' posts.txt\n\n# Extract hex colors\ngrep -oP '#[0-9a-fA-F]{3,8}\\b' styles.css\n```\n\n## Language-Specific Usage\n\n### JavaScript\n\n```javascript\n// Test if a string matches\nconst emailRegex = /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$/;\nemailRegex.test('user@example.com'); // true\n\n// Extract with capture groups\nconst match = '2026-02-03T12:30:00Z'.match(/(\\d{4})-(\\d{2})-(\\d{2})/);\n// match[1] = '2026', match[2] = '02', match[3] = '03'\n\n// Named groups\nconst m = 'John Doe, age 30'.match(/(?\u003cname>[A-Za-z ]+), age (?\u003cage>\\d+)/);\n// m.groups.name = 'John Doe', m.groups.age = '30'\n\n// Find all matches (matchAll returns iterator)\nconst text = 'Call 555-1234 or 555-5678';\nconst matches = [...text.matchAll(/\\d{3}-\\d{4}/g)];\n// [{0: '555-1234', index: 5}, {0: '555-5678', index: 18}]\n\n// Replace with callback\n'hello world'.replace(/\\b\\w/g, c => c.toUpperCase());\n// 'Hello World'\n\n// Replace with named groups\n'2026-02-03'.replace(/(?\u003cy>\\d{4})-(?\u003cm>\\d{2})-(?\u003cd>\\d{2})/, '$\u003cm>/$\u003cd>/$\u003cy>');\n// '02/03/2026'\n\n// Split with regex\n'one, two; three'.split(/[,;]\\s*/);\n// ['one', 'two', 'three']\n```\n\n### Python\n\n```python\nimport re\n\n# Match (anchored to start)\nm = re.match(r'^(\\w+)@(\\w+)\\.(\\w+) , 'user@example.com')\nif m:\n print(m.group(1)) # 'user'\n\n# Search (find first match anywhere)\nm = re.search(r'\\d{3}-\\d{4}', 'Call 555-1234 today')\nprint(m.group()) # '555-1234'\n\n# Find all matches\nemails = re.findall(r'[\\w.+-]+@[\\w.-]+\\.\\w{2,}', text)\n\n# Named groups\nm = re.match(r'(?P\u003cname>\\w+)\\s+(?P\u003cage>\\d+)', 'Alice 30')\nprint(m.group('name')) # 'Alice'\n\n# Substitution\nresult = re.sub(r'\\bfoo\\b', 'bar', 'foo foobar foo')\n# 'bar foobar bar'\n\n# Sub with callback\nresult = re.sub(r'\\b\\w', lambda m: m.group().upper(), 'hello world')\n# 'Hello World'\n\n# Compile for reuse (faster in loops)\npattern = re.compile(r'\\d{4}-\\d{2}-\\d{2}')\ndates = pattern.findall(log_text)\n\n# Multiline and DOTALL\nre.findall(r'^ERROR.* , text, re.MULTILINE) # ^ and $ match line boundaries\nre.search(r'start.*end', text, re.DOTALL) # . matches newlines\n\n# Verbose mode (readable complex patterns)\npattern = re.compile(r'''\n ^ # Start of string\n (?P\u003cyear>\\d{4}) # Year\n -(?P\u003cmonth>\\d{2}) # Month\n -(?P\u003cday>\\d{2}) # Day\n $ # End of string\n''', re.VERBOSE)\n```\n\n### Go\n\n```go\nimport \"regexp\"\n\n// Compile pattern (panics on invalid regex)\nre := regexp.MustCompile(`\\d{4}-\\d{2}-\\d{2}`)\n\n// Match test\nre.MatchString(\"2026-02-03\") // true\n\n// Find first match\nre.FindString(\"Date: 2026-02-03 and 2026-03-01\") // \"2026-02-03\"\n\n// Find all matches\nre.FindAllString(text, -1) // []string of all matches\n\n// Capture groups\nre := regexp.MustCompile(`(\\w+)@(\\w+)\\.(\\w+)`)\nmatch := re.FindStringSubmatch(\"user@example.com\")\n// match[0] = \"user@example.com\", match[1] = \"user\", match[2] = \"example\"\n\n// Named groups\nre := regexp.MustCompile(`(?P\u003cyear>\\d{4})-(?P\u003cmonth>\\d{2})-(?P\u003cday>\\d{2})`)\nmatch := re.FindStringSubmatch(\"2026-02-03\")\nfor i, name := range re.SubexpNames() {\n if name != \"\" {\n fmt.Printf(\"%s: %s\\n\", name, match[i])\n }\n}\n\n// Replace\nre.ReplaceAllString(\"foo123bar\", \"NUM\") // \"fooNUMbar\"\n\n// Replace with function\nre.ReplaceAllStringFunc(text, strings.ToUpper)\n\n// Note: Go uses RE2 syntax — no lookahead/lookbehind\n```\n\n### Command Line (grep/sed)\n\n```bash\n# grep -P uses PCRE (Perl-compatible — full features)\n# grep -E uses Extended regex (no lookahead/lookbehind)\n\n# Find lines matching a pattern\ngrep -P '\\d{3}-\\d{4}' file.txt\n\n# Extract only the matching part\ngrep -oP '\\d{3}-\\d{4}' file.txt\n\n# Invert match (lines NOT matching)\ngrep -vP 'DEBUG|TRACE' app.log\n\n# sed replacement\nsed 's/oldPattern/newText/g' file.txt # Basic\nsed -E 's/foo_([a-z]+)/bar_\\1/g' file.txt # Extended with capture group\n\n# Perl one-liner (most powerful)\nperl -pe 's/(?\u003c=price:\\s)\\d+/0/g' file.txt # Lookbehind works in Perl\n```\n\n## Search-and-Replace Patterns\n\n### Code Refactoring\n\n```bash\n# Rename a variable across files\ngrep -rlP '\\boldName\\b' src/ | xargs sed -i 's/\\boldName\\b/newName/g'\n\n# Convert var to const (JavaScript)\nsed -i -E 's/\\bvar\\b/const/g' src/*.js\n\n# Convert single quotes to double quotes\nsed -i \"s/'/\\\"/g\" src/*.ts\n\n# Add trailing commas to object properties\nsed -i -E 's/^(\\s+\\w+:.+[^,])$/\\1,/' config.json\n\n# U\n\n... (truncated)","Plugin_Install_Column":"","Plugin_Config_Column":"","Plugin_Readme_Column":""},"similar":[{"slug":"catholic-grounding-p26e7i","category":"General","URL":"https://openclawdir.com/skills/catholic-grounding-p26e7i","Type":"Skill","Title":"catholic-grounding","Description":"Help answer questions about Catholicism accurately","GitHub_Link":"https://github.com/trevortomesh"},{"slug":"budget-variance-analyzer-mhjee5","category":"General","URL":"https://openclawdir.com/skills/budget-variance-analyzer-mhjee5","Type":"Skill","Title":"budget-variance-analyzer","Description":"Analyze budget vs actual","GitHub_Link":"https://github.com/datadrivenconstruction"},{"slug":"arbiter-ccv7p2","category":"General","URL":"https://openclawdir.com/skills/arbiter-ccv7p2","Type":"Skill","Title":"arbiter","Description":"Push decisions to Arbiter Zebu for async human review.","GitHub_Link":"https://github.com/5hanth"},{"slug":"agentskills-io-rbgb0x","category":"General","URL":"https://openclawdir.com/skills/agentskills-io-rbgb0x","Type":"Skill","Title":"agentskills-io","Description":"Create, validate, and publish Agent Skills following","GitHub_Link":"https://github.com/killerapp"}]}