{
  "schemaVersion": "1.0",
  "item": {
    "slug": "regex-patterns",
    "name": "Regex Patterns",
    "source": "tencent",
    "type": "skill",
    "category": "开发工具",
    "sourceUrl": "https://clawhub.ai/gitgoodordietrying/regex-patterns",
    "canonicalUrl": "https://clawhub.ai/gitgoodordietrying/regex-patterns",
    "targetPlatform": "OpenClaw"
  },
  "install": {
    "downloadMode": "redirect",
    "downloadUrl": "/downloads/regex-patterns",
    "sourceDownloadUrl": "https://wry-manatee-359.convex.site/api/v1/download?slug=regex-patterns",
    "sourcePlatform": "tencent",
    "targetPlatform": "OpenClaw",
    "installMethod": "Manual import",
    "extraction": "Extract archive",
    "prerequisites": [
      "OpenClaw"
    ],
    "packageFormat": "ZIP package",
    "includedAssets": [
      "SKILL.md"
    ],
    "primaryDoc": "SKILL.md",
    "quickSetup": [
      "Download the package from Yavira.",
      "Extract the archive and review SKILL.md first.",
      "Import or place the package into your OpenClaw setup."
    ],
    "agentAssist": {
      "summary": "Hand the extracted package to your coding agent with a concrete install brief instead of figuring it out manually.",
      "steps": [
        "Download the package from Yavira.",
        "Extract it into a folder your agent can access.",
        "Paste one of the prompts below and point your agent at the extracted folder."
      ],
      "prompts": [
        {
          "label": "New install",
          "body": "I downloaded a skill package from Yavira. Read SKILL.md from the extracted folder and install it by following the included instructions. Tell me what you changed and call out any manual steps you could not complete."
        },
        {
          "label": "Upgrade existing",
          "body": "I downloaded an updated skill package from Yavira. Read SKILL.md from the extracted folder, compare it with my current installation, and upgrade it while preserving any custom configuration unless the package docs explicitly say otherwise. Summarize what changed and any follow-up checks I should run."
        }
      ]
    },
    "sourceHealth": {
      "source": "tencent",
      "slug": "regex-patterns",
      "status": "healthy",
      "reason": "direct_download_ok",
      "recommendedAction": "download",
      "checkedAt": "2026-05-08T01:59:54.481Z",
      "expiresAt": "2026-05-15T01:59:54.481Z",
      "httpStatus": 200,
      "finalUrl": "https://wry-manatee-359.convex.site/api/v1/download?slug=regex-patterns",
      "contentType": "application/zip",
      "probeMethod": "head",
      "details": {
        "probeUrl": "https://wry-manatee-359.convex.site/api/v1/download?slug=regex-patterns",
        "contentDisposition": "attachment; filename=\"regex-patterns-1.0.0.zip\"",
        "redirectLocation": null,
        "bodySnippet": null,
        "slug": "regex-patterns"
      },
      "scope": "item",
      "summary": "Item download looks usable.",
      "detail": "Yavira can redirect you to the upstream package for this item.",
      "primaryActionLabel": "Download for OpenClaw",
      "primaryActionHref": "/downloads/regex-patterns"
    },
    "validation": {
      "installChecklist": [
        "Use the Yavira download entry.",
        "Review SKILL.md after the package is downloaded.",
        "Confirm the extracted package contains the expected setup assets."
      ],
      "postInstallChecks": [
        "Confirm the extracted package includes the expected docs or setup files.",
        "Validate the skill or prompts are available in your target agent workspace.",
        "Capture any manual follow-up steps the agent could not complete."
      ]
    },
    "downloadPageUrl": "https://openagent3.xyz/downloads/regex-patterns",
    "agentPageUrl": "https://openagent3.xyz/skills/regex-patterns/agent",
    "manifestUrl": "https://openagent3.xyz/skills/regex-patterns/agent.json",
    "briefUrl": "https://openagent3.xyz/skills/regex-patterns/agent.md"
  },
  "agentAssist": {
    "summary": "Hand the extracted package to your coding agent with a concrete install brief instead of figuring it out manually.",
    "steps": [
      "Download the package from Yavira.",
      "Extract it into a folder your agent can access.",
      "Paste one of the prompts below and point your agent at the extracted folder."
    ],
    "prompts": [
      {
        "label": "New install",
        "body": "I downloaded a skill package from Yavira. Read SKILL.md from the extracted folder and install it by following the included instructions. Tell me what you changed and call out any manual steps you could not complete."
      },
      {
        "label": "Upgrade existing",
        "body": "I downloaded an updated skill package from Yavira. Read SKILL.md from the extracted folder, compare it with my current installation, and upgrade it while preserving any custom configuration unless the package docs explicitly say otherwise. Summarize what changed and any follow-up checks I should run."
      }
    ]
  },
  "documentation": {
    "source": "clawhub",
    "primaryDoc": "SKILL.md",
    "sections": [
      {
        "title": "Regex Patterns",
        "body": "Practical regular expression cookbook. Patterns for validation, parsing, extraction, and refactoring across JavaScript, Python, Go, and command-line tools."
      },
      {
        "title": "When to Use",
        "body": "Validating user input (email, URL, IP, phone, dates)\nParsing log lines or structured text\nExtracting data from strings (IDs, numbers, tokens)\nSearch-and-replace in code (rename variables, update imports)\nFiltering lines in files or command output\nDebugging regexes that don't match as expected"
      },
      {
        "title": "Metacharacters",
        "body": "PatternMatchesExample.Any character (except newline)a.c matches abc, a1c\\dDigit [0-9]\\d{3} matches 123\\wWord char [a-zA-Z0-9_]\\w+ matches hello_123\\sWhitespace [ \\t\\n\\r\\f]\\s+ matches spaces/tabs\\bWord boundary\\bcat\\b matches cat not scatter^Start of line^Error matches line starting with Error$End of line\\.js$ matches line ending with .js\\D, \\W, \\SNegated: non-digit, non-word, non-space"
      },
      {
        "title": "Quantifiers",
        "body": "PatternMeaning*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)"
      },
      {
        "title": "Groups and Alternation",
        "body": "PatternMeaning(abc)Capture group(?:abc)Non-capturing group(?P<name>abc)Named group (Python)(?<name>abc)Named group (JS/Go)a|bAlternation (a or b)[abc]Character class (a, b, or c)[^abc]Negated class (not a, b, or c)[a-z]Range"
      },
      {
        "title": "Lookahead and Lookbehind",
        "body": "PatternMeaning(?=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)"
      },
      {
        "title": "Email",
        "body": "# 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,})+$"
      },
      {
        "title": "URL",
        "body": "# 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]*)?"
      },
      {
        "title": "IP Addresses",
        "body": "# 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}"
      },
      {
        "title": "Phone Numbers",
        "body": "# 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}"
      },
      {
        "title": "Dates and Times",
        "body": "# 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"
      },
      {
        "title": "Passwords (Strength Check)",
        "body": "# At least 8 chars, 1 upper, 1 lower, 1 digit, 1 special\n^(?=.*[a-z])(?=.*[A-Z])(?=.*\\d)(?=.*[!@#$%^&*()_+=-]).{8,}$"
      },
      {
        "title": "UUIDs",
        "body": "[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}"
      },
      {
        "title": "Semantic Version",
        "body": "\\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"
      },
      {
        "title": "Log Lines",
        "body": "# 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"
      },
      {
        "title": "Code Patterns",
        "body": "# 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'"
      },
      {
        "title": "Data Extraction",
        "body": "# 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<>\"]+' 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"
      },
      {
        "title": "JavaScript",
        "body": "// 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(/(?<name>[A-Za-z ]+), age (?<age>\\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(/(?<y>\\d{4})-(?<m>\\d{2})-(?<d>\\d{2})/, '$<m>/$<d>/$<y>');\n// '02/03/2026'\n\n// Split with regex\n'one, two;  three'.split(/[,;]\\s*/);\n// ['one', 'two', 'three']"
      },
      {
        "title": "Python",
        "body": "import 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<name>\\w+)\\s+(?P<age>\\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<year>\\d{4})     # Year\n    -(?P<month>\\d{2})   # Month\n    -(?P<day>\\d{2})     # Day\n    $                   # End of string\n''', re.VERBOSE)"
      },
      {
        "title": "Go",
        "body": "import \"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<year>\\d{4})-(?P<month>\\d{2})-(?P<day>\\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"
      },
      {
        "title": "Command Line (grep/sed)",
        "body": "# 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/(?<=price:\\s)\\d+/0/g' file.txt    # Lookbehind works in Perl"
      },
      {
        "title": "Code Refactoring",
        "body": "# 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# Update import paths\nsed -i 's|from '\\''../old-path/|from '\\''../new-path/|g' src/*.ts\n\n# Convert snake_case to camelCase (Python → JavaScript naming)\nperl -pe 's/_([a-z])/uc($1)/ge' file.txt"
      },
      {
        "title": "Text Cleanup",
        "body": "# Remove trailing whitespace\nsed -i 's/[[:space:]]*$//' file.txt\n\n# Remove blank lines\nsed -i '/^$/d' file.txt\n\n# Remove duplicate blank lines (keep at most one)\nsed -i '/^$/N;/^\\n$/d' file.txt\n\n# Trim leading and trailing whitespace from each line\nsed -i 's/^[[:space:]]*//;s/[[:space:]]*$//' file.txt\n\n# Remove HTML tags\nsed 's/<[^>]*>//g' file.html\n\n# Remove ANSI color codes\nsed 's/\\x1b\\[[0-9;]*m//g' output.txt"
      },
      {
        "title": "Greedy vs lazy matching",
        "body": "Pattern: <.*>     Input: <b>bold</b>\nGreedy  matches: <b>bold</b>     (entire string between first < and last >)\nLazy    matches: <b>              (stops at first >)\nPattern: <.*?>    (lazy version)"
      },
      {
        "title": "Escaping special characters",
        "body": "Characters that need escaping in regex: . * + ? ^ $ { } [ ] ( ) | \\\nIn character classes []: only ] - ^ \\ need escaping\n\n# To match a literal dot:  \\.\n# To match a literal *:    \\*\n# To match a literal \\:    \\\\\n# To match [ or ]:         \\[ or \\]"
      },
      {
        "title": "Newlines and multiline",
        "body": "By default . does NOT match newline.\nBy default ^ and $ match start/end of STRING.\n\n# To make . match newlines:\nJavaScript: /pattern/s (dotAll flag)\nPython: re.DOTALL or re.S\nGo: (?s) inline flag\n\n# To make ^ $ match line boundaries:\nJavaScript: /pattern/m (multiline flag)\nPython: re.MULTILINE or re.M\nGo: (?m) inline flag"
      },
      {
        "title": "Backtracking and performance",
        "body": "# Catastrophic backtracking (avoid these patterns on untrusted input):\n(a+)+        # Nested quantifiers\n(a|a)+       # Overlapping alternation\n(.*a){10}    # Ambiguous .* with repetition\n\n# Safe alternatives:\n[a]+         # Instead of (a+)+\na+           # Instead of (a|a)+\n[^a]*a       # Possessive/atomic instead of .*a"
      },
      {
        "title": "Tips",
        "body": "Start simple and add complexity. \\d+ is almost always enough — you rarely need [0-9]+.\nTest your regex on real data, not just the happy path. Edge cases (empty strings, special characters, Unicode) break naive patterns.\nUse non-capturing groups (?:...) when you don't need the captured value. It's slightly faster and cleaner.\nIn JavaScript, always use the g flag for matchAll and global replace. Without it, only the first match is found/replaced.\nGo's regexp package uses RE2 (no lookahead/lookbehind). If you need those, use a different approach or the regexp2 package.\ngrep -P (PCRE) is the most powerful command-line regex. Use it over grep -E when you need lookahead, \\d, or \\b.\nFor complex patterns, use verbose mode (re.VERBOSE in Python, /x in Perl) with comments explaining each part.\nRegex is the wrong tool for parsing HTML, XML, or JSON. Use a proper parser. Regex works for extracting simple values from these formats, not for structural parsing."
      }
    ],
    "body": "Regex Patterns\n\nPractical regular expression cookbook. Patterns for validation, parsing, extraction, and refactoring across JavaScript, Python, Go, and command-line tools.\n\nWhen to Use\nValidating user input (email, URL, IP, phone, dates)\nParsing log lines or structured text\nExtracting data from strings (IDs, numbers, tokens)\nSearch-and-replace in code (rename variables, update imports)\nFiltering lines in files or command output\nDebugging regexes that don't match as expected\nQuick Reference\nMetacharacters\nPattern\tMatches\tExample\n.\tAny character (except newline)\ta.c matches abc, a1c\n\\d\tDigit [0-9]\t\\d{3} matches 123\n\\w\tWord char [a-zA-Z0-9_]\t\\w+ matches hello_123\n\\s\tWhitespace [ \\t\\n\\r\\f]\t\\s+ matches spaces/tabs\n\\b\tWord boundary\t\\bcat\\b matches cat not scatter\n^\tStart of line\t^Error matches line starting with Error\n$\tEnd of line\t\\.js$ matches line ending with .js\n\\D, \\W, \\S\tNegated: non-digit, non-word, non-space\t\nQuantifiers\nPattern\tMeaning\n*\t0 or more (greedy)\n+\t1 or more (greedy)\n?\t0 or 1 (optional)\n{3}\tExactly 3\n{2,5}\tBetween 2 and 5\n{3,}\t3 or more\n*?, +?\tLazy (match as few as possible)\nGroups and Alternation\nPattern\tMeaning\n(abc)\tCapture group\n(?:abc)\tNon-capturing group\n(?P<name>abc)\tNamed group (Python)\n(?<name>abc)\tNamed group (JS/Go)\na|b\tAlternation (a or b)\n[abc]\tCharacter class (a, b, or c)\n[^abc]\tNegated class (not a, b, or c)\n[a-z]\tRange\nLookahead and Lookbehind\nPattern\tMeaning\n(?=abc)\tPositive lookahead (followed by abc)\n(?!abc)\tNegative lookahead (not followed by abc)\n(?<=abc)\tPositive lookbehind (preceded by abc)\n(?<!abc)\tNegative lookbehind (not preceded by abc)\nValidation Patterns\nEmail\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\nURL\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\nIP Addresses\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\nPhone Numbers\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\nDates and Times\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\nPasswords (Strength Check)\n# At least 8 chars, 1 upper, 1 lower, 1 digit, 1 special\n^(?=.*[a-z])(?=.*[A-Z])(?=.*\\d)(?=.*[!@#$%^&*()_+=-]).{8,}$\n\nUUIDs\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\nSemantic Version\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\nParsing Patterns\nLog Lines\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\nCode Patterns\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\nData Extraction\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<>\"]+' 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\nLanguage-Specific Usage\nJavaScript\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(/(?<name>[A-Za-z ]+), age (?<age>\\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(/(?<y>\\d{4})-(?<m>\\d{2})-(?<d>\\d{2})/, '$<m>/$<d>/$<y>');\n// '02/03/2026'\n\n// Split with regex\n'one, two;  three'.split(/[,;]\\s*/);\n// ['one', 'two', 'three']\n\nPython\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<name>\\w+)\\s+(?P<age>\\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<year>\\d{4})     # Year\n    -(?P<month>\\d{2})   # Month\n    -(?P<day>\\d{2})     # Day\n    $                   # End of string\n''', re.VERBOSE)\n\nGo\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<year>\\d{4})-(?P<month>\\d{2})-(?P<day>\\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\nCommand Line (grep/sed)\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/(?<=price:\\s)\\d+/0/g' file.txt    # Lookbehind works in Perl\n\nSearch-and-Replace Patterns\nCode Refactoring\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# Update import paths\nsed -i 's|from '\\''../old-path/|from '\\''../new-path/|g' src/*.ts\n\n# Convert snake_case to camelCase (Python → JavaScript naming)\nperl -pe 's/_([a-z])/uc($1)/ge' file.txt\n\nText Cleanup\n# Remove trailing whitespace\nsed -i 's/[[:space:]]*$//' file.txt\n\n# Remove blank lines\nsed -i '/^$/d' file.txt\n\n# Remove duplicate blank lines (keep at most one)\nsed -i '/^$/N;/^\\n$/d' file.txt\n\n# Trim leading and trailing whitespace from each line\nsed -i 's/^[[:space:]]*//;s/[[:space:]]*$//' file.txt\n\n# Remove HTML tags\nsed 's/<[^>]*>//g' file.html\n\n# Remove ANSI color codes\nsed 's/\\x1b\\[[0-9;]*m//g' output.txt\n\nCommon Gotchas\nGreedy vs lazy matching\nPattern: <.*>     Input: <b>bold</b>\nGreedy  matches: <b>bold</b>     (entire string between first < and last >)\nLazy    matches: <b>              (stops at first >)\nPattern: <.*?>    (lazy version)\n\nEscaping special characters\nCharacters that need escaping in regex: . * + ? ^ $ { } [ ] ( ) | \\\nIn character classes []: only ] - ^ \\ need escaping\n\n# To match a literal dot:  \\.\n# To match a literal *:    \\*\n# To match a literal \\:    \\\\\n# To match [ or ]:         \\[ or \\]\n\nNewlines and multiline\nBy default . does NOT match newline.\nBy default ^ and $ match start/end of STRING.\n\n# To make . match newlines:\nJavaScript: /pattern/s (dotAll flag)\nPython: re.DOTALL or re.S\nGo: (?s) inline flag\n\n# To make ^ $ match line boundaries:\nJavaScript: /pattern/m (multiline flag)\nPython: re.MULTILINE or re.M\nGo: (?m) inline flag\n\nBacktracking and performance\n# Catastrophic backtracking (avoid these patterns on untrusted input):\n(a+)+        # Nested quantifiers\n(a|a)+       # Overlapping alternation\n(.*a){10}    # Ambiguous .* with repetition\n\n# Safe alternatives:\n[a]+         # Instead of (a+)+\na+           # Instead of (a|a)+\n[^a]*a       # Possessive/atomic instead of .*a\n\nTips\nStart simple and add complexity. \\d+ is almost always enough — you rarely need [0-9]+.\nTest your regex on real data, not just the happy path. Edge cases (empty strings, special characters, Unicode) break naive patterns.\nUse non-capturing groups (?:...) when you don't need the captured value. It's slightly faster and cleaner.\nIn JavaScript, always use the g flag for matchAll and global replace. Without it, only the first match is found/replaced.\nGo's regexp package uses RE2 (no lookahead/lookbehind). If you need those, use a different approach or the regexp2 package.\ngrep -P (PCRE) is the most powerful command-line regex. Use it over grep -E when you need lookahead, \\d, or \\b.\nFor complex patterns, use verbose mode (re.VERBOSE in Python, /x in Perl) with comments explaining each part.\nRegex is the wrong tool for parsing HTML, XML, or JSON. Use a proper parser. Regex works for extracting simple values from these formats, not for structural parsing."
  },
  "trust": {
    "sourceLabel": "tencent",
    "provenanceUrl": "https://clawhub.ai/gitgoodordietrying/regex-patterns",
    "publisherUrl": "https://clawhub.ai/gitgoodordietrying/regex-patterns",
    "owner": "gitgoodordietrying",
    "version": "1.0.0",
    "license": null,
    "verificationStatus": "Indexed source record"
  },
  "links": {
    "detailUrl": "https://openagent3.xyz/skills/regex-patterns",
    "downloadUrl": "https://openagent3.xyz/downloads/regex-patterns",
    "agentUrl": "https://openagent3.xyz/skills/regex-patterns/agent",
    "manifestUrl": "https://openagent3.xyz/skills/regex-patterns/agent.json",
    "briefUrl": "https://openagent3.xyz/skills/regex-patterns/agent.md"
  }
}