AXe Skills HubSearch /

← All skills

regex-text-processing

AXe First-party 

Reference: full SKILL.md

Below is the complete skill definition this hub loads when the skill is triggered — what the agent sees as its instructions, verbatim and unabridged.

Regex & Text Processing

Role

You are an elite text processing engineer. You write precise regex patterns, build robust

text pipelines, and handle every edge case in parsing, normalization, and template rendering.

Part 1: Advanced Regex Patterns

import re

# Email validation (RFC 5322 simplified)
EMAIL = re.compile(r"[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}")

# URL extraction
URL = re.compile(
    r"https?://(?:[-\w.]|(?:%[\da-fA-F]{2}))+[/\w\-.~:/?#\[\]@!$&'()*+,;=%]*"
)

# Phone numbers (international)
PHONE = re.compile(r"\+?1?[-.\s]?\(?\d{3}\)?[-.\s]?\d{3}[-.\s]?\d{4}")

# ISO date/datetime
ISO_DATE = re.compile(r"\d{4}-(?:0[1-9]|1[0-2])-(?:0[1-9]|[12]\d|3[01])")
ISO_DATETIME = re.compile(
    r"\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d+)?(?:Z|[+-]\d{2}:\d{2})?"
)

# IP addresses
IPV4 = re.compile(r"\b(?:\d{1,3}\.){3}\d{1,3}\b")

# Semantic version
SEMVER = re.compile(r"\bv?(\d+)\.(\d+)\.(\d+)(?:-([a-zA-Z0-9.]+))?\b")

# JSON keys extraction
JSON_KEY = re.compile(r'"(\w+)"\s*:')

# Log parsing: [timestamp] [level] message
LOG_LINE = re.compile(
    r"\[(?P<ts>\d{4}-\d{2}-\d{2}\s\d{2}:\d{2}:\d{2})\]\s+"
    r"\[(?P<level>\w+)\]\s+"
    r"(?P<message>.*)"
)

# Multi-pattern extraction
def extract_all(text: str) -> dict:
    return {
        "emails": EMAIL.findall(text),
        "urls": URL.findall(text),
        "phones": PHONE.findall(text),
        "dates": ISO_DATE.findall(text),
        "ips": IPV4.findall(text),
    }

Part 2: Named Groups & Lookaround

# Named groups for structured parsing
LOG_PATTERN = re.compile(
    r"(?P<ip>\d+\.\d+\.\d+\.\d+)\s-\s"
    r"(?P<user>\S+)\s"
    r"\[(?P<date>[^\]]+)\]\s"
    r'"(?P<method>\w+)\s(?P<path>\S+)\sHTTP/\S+"\s'
    r"(?P<status>\d{3})\s(?P<size>\d+)"
)

def parse_access_log(line: str) -> dict | None:
    if m := LOG_PATTERN.match(line):
        return m.groupdict()
    return None

# Lookahead/lookbehind
# Password validation: 8+ chars, uppercase, lowercase, digit, special
PASSWORD = re.compile(
    r"^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[@$!%*?&])[A-Za-z\d@$!%*?&]{8,}$"
)

# Extract words NOT preceded by @ (ignore mentions)
NON_MENTION_WORDS = re.compile(r"(?<!@)\b[a-zA-Z]+\b")

# Match content between balanced delimiters (non-greedy)
TEMPLATE_VAR = re.compile(r"\{\{(.+?)\}\}")
BLOCK_TAG = re.compile(r"\{%\s*(\w+)\s*(.*?)\s*%\}")

# Replace with function
def redact_emails(text: str) -> str:
    return EMAIL.sub(lambda m: m.group().split("@")[0][:2] + "***@" + m.group().split("@")[1], text)

# Conditional replacement
def smart_replace(text: str, pattern: str, replacer: Callable[[re.Match], str]) -> str:
    return re.sub(pattern, replacer, text)

Part 3: Text Normalization

import unicodedata, html

def normalize_text(text: str) -> str:
    """Full text normalization pipeline."""
    text = html.unescape(text)                          # &amp; -> &
    text = unicodedata.normalize("NFKC", text)          # Unicode normalization
    text = re.sub(r"[\u200b\u200c\u200d\ufeff]", "", text)  # Zero-width chars
    text = re.sub(r"[\u2018\u2019]", "'", text)         # Smart quotes -> ASCII
    text = re.sub(r"[\u201c\u201d]", '"', text)
    text = re.sub(r"[\u2013\u2014]", "-", text)         # Em/en dash
    text = re.sub(r"\u2026", "...", text)                # Ellipsis
    text = re.sub(r"\s+", " ", text).strip()             # Collapse whitespace
    return text

def slugify(text: str) -> str:
    text = unicodedata.normalize("NFKD", text).encode("ascii", "ignore").decode()
    text = re.sub(r"[^\w\s-]", "", text.lower())
    return re.sub(r"[-\s]+", "-", text).strip("-")

def extract_sentences(text: str) -> list[str]:
    return re.split(r"(?<=[.!?])\s+(?=[A-Z])", text)

def remove_stopwords(tokens: list[str], stopwords: set[str] | None = None) -> list[str]:
    stops = stopwords or {"the", "a", "an", "is", "are", "was", "were", "in", "on", "at", "to", "for", "of", "and", "or", "but", "not", "with", "this", "that", "it", "be", "as", "by"}
    return [t for t in tokens if t.lower() not in stops]

Part 4: Fuzzy Matching with RapidFuzz

from rapidfuzz import fuzz, process

def fuzzy_search(query: str, choices: list[str], threshold: int = 70) -> list[tuple[str, float]]:
    results = process.extract(query, choices, scorer=fuzz.WRatio, limit=10)
    return [(match, score) for match, score, _ in results if score >= threshold]

def deduplicate_names(names: list[str], threshold: int = 85) -> list[str]:
    """Merge near-duplicate names."""
    clusters: list[list[str]] = []
    used = set()
    for name in names:
        if name in used:
            continue
        cluster = [name]
        used.add(name)
        for other in names:
            if other not in used and fuzz.ratio(name.lower(), other.lower()) >= threshold:
                cluster.append(other)
                used.add(other)
        clusters.append(cluster)
    return [max(c, key=len) for c in clusters]  # pick longest variant

def fuzzy_match_records(source: list[dict], target: list[dict],
                        key: str, threshold: int = 80) -> list[tuple[dict, dict, float]]:
    target_names = [r[key] for r in target]
    matches = []
    for record in source:
        results = process.extractOne(record[key], target_names, scorer=fuzz.WRatio)
        if results and results[1] >= threshold:
            matched_idx = target_names.index(results[0])
            matches.append((record, target[matched_idx], results[1]))
    return matches

Part 5: Entity Extraction

# Simple rule-based entity extraction
ENTITY_PATTERNS = {
    "money": re.compile(r"\$[\d,]+(?:\.\d{2})?|\d+(?:\.\d{2})?\s*(?:USD|EUR|GBP)"),
    "percentage": re.compile(r"\d+(?:\.\d+)?%"),
    "date": re.compile(r"\b(?:Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)\w*\s+\d{1,2},?\s+\d{4}\b"),
    "time": re.compile(r"\b\d{1,2}:\d{2}(?::\d{2})?\s*(?:AM|PM|am|pm)?\b"),
    "hex_color": re.compile(r"#[0-9a-fA-F]{3,8}\b"),
    "file_path": re.compile(r"(?:/[\w.-]+)+|(?:[A-Z]:\\(?:[\w.-]+\\)*)[\w.-]+"),
    "git_sha": re.compile(r"\b[0-9a-f]{7,40}\b"),
}

def extract_entities(text: str) -> dict[str, list[str]]:
    return {name: pattern.findall(text) for name, pattern in ENTITY_PATTERNS.items()}

# Structured data extraction from unstructured text
def extract_key_value_pairs(text: str) -> dict[str, str]:
    """Extract 'Key: Value' pairs from text."""
    pattern = re.compile(r"^([A-Z][\w\s]+?):\s*(.+)$", re.MULTILINE)
    return dict(pattern.findall(text))

Part 6: Jinja2 Template Engine

from jinja2 import Environment, BaseLoader, select_autoescape, StrictUndefined

env = Environment(
    loader=BaseLoader(),
    autoescape=select_autoescape(["html"]),
    undefined=StrictUndefined,
    trim_blocks=True,
    lstrip_blocks=True,
)

# Custom filters
env.filters["slugify"] = slugify
env.filters["truncate_words"] = lambda s, n: " ".join(s.split()[:n]) + ("..." if len(s.split()) > n else "")

def render_template_string(template_str: str, context: dict) -> str:
    return env.from_string(template_str).render(**context)

# Generate code from templates
CODE_TEMPLATE = """
class {{ class_name }}(BaseModel):
    {% for field in fields %}
    {{ field.name }}: {{ field.type }}{% if field.default is not none %} = {{ field.default }}{% endif %}
    {% endfor %}

    {% for method in methods %}
    def {{ method.name }}(self{% for arg in method.args %}, {{ arg }}{% endfor %}):
        {{ method.body | indent(8) }}
    {% endfor %}
"""

def generate_model(spec: dict) -> str:
    return render_template_string(CODE_TEMPLATE, spec)

Part 7: Markdown/HTML Conversion

import markdown
from markupsafe import Markup

def md_to_html(text: str, extensions: list[str] | None = None) -> str:
    exts = extensions or ["fenced_code", "tables", "toc", "codehilite", "nl2br"]
    return markdown.markdown(text, extensions=exts)

def html_to_text(html: str) -> str:
    """Strip HTML tags, decode entities, clean whitespace."""
    text = re.sub(r"<br\s*/?>", "\n", html)
    text = re.sub(r"<p[^>]*>", "\n", text)
    text = re.sub(r"<[^>]+>", "", text)
    text = html_module.unescape(text)
    return re.sub(r"\n{3,}", "\n\n", text).strip()

def extract_markdown_sections(md_text: str) -> dict[str, str]:
    """Parse markdown into {heading: content} dict."""
    sections = {}
    current_heading = "preamble"
    current_content = []
    for line in md_text.split("\n"):
        if m := re.match(r"^(#{1,6})\s+(.+)$", line):
            if current_content:
                sections[current_heading] = "\n".join(current_content).strip()
            current_heading = m.group(2)
            current_content = []
        else:
            current_content.append(line)
    if current_content:
        sections[current_heading] = "\n".join(current_content).strip()
    return sections

AXE MCP Server Integration

Every skill in the AXE Skills Hub runs with access to the AXE MCP Server — giving it the full fleet intelligence toolkit automatically. No setup required; tools are available in any AXE-powered session.

Core Tools Available

CategoryToolsUse Case
Memoryread_memory, write_memory, list_memoryPersist context across sessions
Webweb_search, web_fetchLive data, docs, research
File Opsread_file, write_fileRead/write any local file
Fleetfleet_ssh, axe_pushRun commands on JL2/JL3/JL4, send notifications
AI Modelsquery_team_channel, get_partner_stateCross-agent coordination
Dataqdrant_search, qdrant_storeSemantic memory & vector search
Pipelinehydra_addAdd high-quality outputs to Edge training
Skillshub_list_skills, hub_get_skill, hub_search_skills, hub_get_registry, hub_skill_metadataChain skills together
Secretsget_secretRetrieve API keys securely

Quick Start

# In any AXE session, tools are pre-loaded. Example chaining:

# 1. Search for context
results = qdrant_search("user query here", collection="axe_persistent_memory")

# 2. Fetch live data if needed
content = web_fetch("https://docs.example.com/api")

# 3. Write result to memory for next session
write_memory("shared/last_result.md", output)

# 4. Log quality output to Edge training pipeline
hydra_add(prompt=user_query, response=output, score=0.9, source="skill-name")

Edge Training Integration

High-quality skill outputs are automatically eligible for Edge model training via hydra_add. When a response scores ≥0.85 in evals, pipe it to the Hydra pipeline to compound Edge's knowledge. This is how skills make Edge smarter over time.

# After generating a high-quality response:
hydra_add(
    prompt=user_input,
    response=final_output,
    score=0.9,          # eval score
    source="skill-name" # tracks provenance
)

Metadata

Category
General
Tier
community
Version
1.0.0
License
MIT
Path
skills/regex-text-processing/SKILL.md

Use with an agent

Fetch this skill’s definition over the open API — no key required.

curl -s /v1/skills/regex-text-processing

View source ↗