# Regex Capture Groups to CSV

Scan text with a regex and get CSV: one row per match, named capture groups as columns. Pick the delimiter, quoting, and columns — all in your browser.

## Run it

- **CLI:** `gizza tool regex-capture-to-csv "10.0.0.5 GET /index.html 200
10.0.0.9 POST /api/login 401" 'pattern=(?<ip>\S+) (?<method>[A-Z]+) (?<path>\S+) (?<status>\d{3})'`
- **Web:** https://gizza.ai/tools/regex-capture-to-csv/
- **Agents:** machine-readable descriptor (parameters JSON Schema) at https://gizza.ai/tools/regex-capture-to-csv/tool.json

## Inputs

- `text` — Text to scan _(field)_
- `pattern` — Regex (named capture groups become columns) _(field)_
- `columns` — Columns (blank = all, in pattern order) _(field)_
- `delimiter` — Delimiter _(field)_
- `header` — Header row of column names _(field)_
- `quoting` — Quoting _(field)_
- `line_ending` — Line endings _(field)_
- `ignore_case` — Ignore case _(field)_
- `multiline` — Multiline (^ and $ per line) _(field)_
- `dotall` — Dot matches newlines (match across lines) _(field)_
- `unique` — Drop duplicate rows _(field)_
- `sort` — Sort rows _(field)_

## Output

- CSV (text)

## Query parameters

Open the tool pre-filled and auto-run via URL:

- `text` — Text to scan
- `pattern` — Regex (named capture groups become columns)
- `columns` — Columns (blank = all, in pattern order)
- `delimiter` — Delimiter
- `header` — Header row of column names
- `quoting` — Quoting
- `line_ending` — Line endings
- `ignore_case` — Ignore case
- `multiline` — Multiline (^ and $ per line)
- `dotall` — Dot matches newlines (match across lines)
- `unique` — Drop duplicate rows
- `sort` — Sort rows

Example: `https://gizza.ai/tools/regex-capture-to-csv/?text=10.0.0.5%20GET%20%2Findex.html%20200%0A10.0.0.9%20POST%20%2Fapi%2Flogin%20401&pattern=%28%3F%3Cip%3E%5CS%2B%29%20%28%3F%3Cmethod%3E%5BA-Z%5D%2B%29%20%28%3F%3Cpath%3E%5CS%2B%29%20%28%3F%3Cstatus%3E%5Cd%7B3%7D%29&columns=status%2C%20ip&delimiter=%2C%20or%20tab%2C%20semicolon%2C%20pipe&header=true&quoting=minimal&line_ending=lf&ignore_case=true&multiline=true&dotall=true&unique=true&sort=true`

---

## About this tool

Regular expressions are great at finding things in messy text; spreadsheets are great at
everything after that. This tool joins the two: it runs your pattern over the whole input and
writes **one CSV row per match**, using the pattern's capture groups as columns.

Name your groups — `(?<name>…)` or `(?P<name>…)` — and those names become the header row. A
pattern with plain unnamed groups gets `column1`, `column2`, … instead, and a pattern with no
groups at all produces a single `match` column holding each whole match, so any regex you already
have works without editing.

Everything runs locally in your browser: the text you paste never leaves the page.

### Worked example

Input text:

```
2026-07-20 14:03:11 ERROR auth Failed login for alice
2026-07-20 14:03:15 INFO http GET /health 200
```

Pattern:

```
(?<date>\S+) (?<time>\S+) (?<level>[A-Z]+) (?<module>\S+) (?<message>.*)
```

Output CSV (default settings — comma delimiter, header on, minimal quoting):

```
date,time,level,module,message
2026-07-20,14:03:11,ERROR,auth,Failed login for alice
2026-07-20,14:03:15,INFO,http,GET /health 200
```

Set **Columns** to `level, message` to emit just those two, in that order. Switch the delimiter to
`tab` for TSV, or line endings to CRLF when the file is headed for Excel on Windows.

### What you can control

- **Columns** — pick a subset and reorder it; blank means every group in pattern order.
- **Delimiter** — a single character, `\t`, or the keywords `comma`, `semicolon`, `tab`, `pipe`,
  `colon`, `space`.
- **Header row** — turn it off to append rows to an existing file.
- **Quoting** — *minimal* quotes only fields containing the delimiter, a quote, or a line break;
  *all* quotes every field. Embedded quotes are always doubled (`"` → `""`), per RFC 4180.
- **Line endings** — LF or CRLF.
- **Regex flags** — ignore case (`i`), multiline `^`/`$` (`m`), and dot-matches-newline (`s`).
- **Dedupe and sort** — drop repeated rows, then sort them lexicographically.

### Limits and edge cases

- Input is capped at **1 MB** and **100,000 rows**; larger inputs return an explanatory error
  instead of hanging the tab.
- A capture group that did not participate in a match (an optional group) becomes an **empty
  field**, so every row has the same number of columns.
- If the pattern has named groups, unnamed groups in the same pattern are ignored.
- If nothing matches, you get an error rather than an empty file — that is almost always a pattern
  bug worth seeing.
- Syntax is the Rust `regex` crate's: no backreferences and no lookaround. Character classes,
  non-greedy quantifiers, alternation, anchors, and Unicode classes all work.

## FAQ

<details>
<summary>How do I name the columns in my CSV?</summary>

Name the capture groups. `(?<ip>\S+) (?<status>\d{3})` produces a CSV with the header `ip,status`.
Both syntaxes are accepted — `(?<name>…)` and `(?P<name>…)`. If you would rather keep the pattern
untouched, leave the groups unnamed and the columns come out as `column1`, `column2`, … which you
can rename in your spreadsheet.

</details>

<details>
<summary>What happens to commas, quotes, and newlines inside a captured value?</summary>

They are escaped properly. A field containing the delimiter, a double quote, or a line break is
wrapped in double quotes, and any quote inside it is doubled — so `say "hi", now` becomes
`"say ""hi"", now"`. That is the RFC 4180 convention every spreadsheet understands. Choose
*All fields quoted* if your downstream tool prefers a uniformly quoted file.

</details>

<details>
<summary>Can one row come from text that spans several lines?</summary>

Yes. The pattern is applied to the whole input, not line by line. Turn on **Dot matches newlines**
so `.` crosses line boundaries, and a pattern like `<td>(?<cell>.+?)</td>` will capture a cell whose
content is wrapped over two lines. The captured newline is preserved inside a quoted CSV field.

</details>

<details>
<summary>Why do I get "no matches" when the pattern looks right?</summary>

The usual causes are case (turn on **Ignore case**), anchors (`^` and `$` only match the very start
and end of the text unless **Multiline** is on), and `.` not crossing line breaks (turn on **Dot
matches newlines**). Also remember that backreferences and lookaround are not supported by this
regex engine — a pattern copied from a PCRE tester that uses `(?=…)` will fail to compile and you
will get an "invalid regular expression" error instead.

</details>

<details>
<summary>How do I get a TSV, or a file Excel opens cleanly?</summary>

Set the delimiter to `tab` for TSV. For Excel on Windows, set line endings to CRLF; keep the header
row on so the columns are labelled. If your data contains semicolons and your locale's Excel splits
on semicolons, pick a different delimiter — any single character is allowed.

</details>

<details>
<summary>Is the same thing available on the command line?</summary>

Yes — every tool here is also a CLI command with the same parameters, so a pattern you tuned on
this page can be dropped straight into a script or piped into another tool. The page shows the
exact command for the values you have entered.

</details>

## Related tools

- [Regex to JSON](https://gizza.ai/tools/regex-to-json/): Parse each line of text with a named-capture regex and turn it into structured JSON — group names become keys. Type coercion, NDJSON output, in your browser.
- [Log Parser](https://gizza.ai/tools/log-parser/): Free log parser — auto-detects JSON/NDJSON, logfmt, syslog and Apache/nginx access logs into a filterable table, JSON, or CSV. Runs in your browser, no upload.
- [Log to Table](https://gizza.ai/tools/log-to-table/): Turn semi-structured log lines into a Markdown table, CSV, TSV, or JSON using named regex groups and presets for Apache, syslog, and log4j-style logs.
- [Bulk Regex Matcher](https://gizza.ai/tools/regex-bulk-match/): Check one regular expression against a pasted list of lines. See match/no-match status, captures, positions, JSON, or CSV output. Runs locally.
- [Rule-based text extractor](https://gizza.ai/tools/rule-based-extractor/): Turn logs, invoices or scraped text into structured data with named regex rules. Grok-style %{PATTERN:field} shortcuts, JSON/CSV output, per-rule report.
