CSV Find and Replace

Find and replace across a whole CSV, or inside one column. The search is literal text by default, so a full stop means a full stop. Switch on the regular expression mode when you need patterns and capture groups. The match count updates as you type, which tells you immediately whether the term is right. Nothing is uploaded.

Replacing values in a spreadsheet instead? Convert the workbook first, then come back.

Literal means literal

The commonest bug in browser find-and-replace tools is that the search box is fed straight into a regular expression. It looks fine until somebody searches for a price. Type 1.50 and a regex-backed tool will happily match 1x50, because a dot means any character. Type (EU) and it matches EU anywhere, brackets silently gone. Type [draft] and it matches any single one of the letters d, r, a, f and t. Type C++ and it throws.

Here, the search is literal until you say otherwise. Every character that means something to a regular expression is escaped before the search runs, so 1.50 finds 1.50 and nothing else, and C++ is a search rather than a syntax error. The Pattern control is where you opt into the other behavior, and when you do the error message for a broken pattern tells you it is broken instead of leaving the file unchanged.

The same rule applies to the replacement. $1 only means "the first capture group" in pattern mode. In literal mode it is written out as the two characters it is, and if you type it while the pattern switch is off the page points out that this is happening.

Worked example: two replacements on one file

Start with companies.csv:

id,company
1,Acme Ltd
2,Globex Ltd
3,ltd Holdings

Search for Ltd and replace with Limited, leaving everything else alone:

id,company
1,Acme Limited
2,Globex Limited
3,ltd Holdings

3 rows · across every column · plain text · case-sensitive
· 2 matches in 2 cells · 2 cells changed

Row 3 is untouched, because the search is case-sensitive by default and ltd is not Ltd. That default is deliberate: case-insensitive replacement is how Mark in a notes column becomes Marketing. Switch Letter case to Ignore case and row 3 becomes Limited Holdings, with the count rising to 3.

Now a pattern, to flip a name around. In a file whose name column holds Lovelace, Ada, switch Pattern on and use:

Find:         (\w+), (\w+)
Replace with: $2 $1
Result:       Ada Lovelace

Two capture groups, referred to in the replacement by number. If you write $1 in the replacement while the pattern has no brackets in it, the page tells you the group is empty rather than letting you download a column of blanks.

The three counts, and what a gap between them means

Above the result there are three numbers: how many matches were found, how many cells those matches were spread across, and how many cells actually came out different. They are not the same number, and the differences are informative.

  • Matches higher than cells means some cells contain the term more than once. Worth checking before you replace something with a longer string, because that cell is about to grow.
  • Cells changed lower than cells matched means the replacement is identical to what was found. Usually a typo in one of the two boxes, occasionally a deliberate no-op while you are still counting things. The page says so explicitly.
  • Zero matches is the useful one. Because the counts recompute as you type, a term that finds nothing tells you within a keystroke or two, rather than after you have downloaded a file and diffed it. The warning suggests the two usual causes: the letter case, and the scope being set to a single column that is not the one you meant.

There is no Run button anywhere on this page. Every control recomputes the whole result immediately, so the counts are always describing the settings currently on screen.

Whole cell, one column, and the header row

Three controls exist to stop a replacement going further than you meant.

Whole cell only makes the search match a cell exactly, end to end, rather than anywhere inside it. This is the setting for normalizing a set of status values: replacing the cell N/A with nothing is safe, while replacing the substring N/A with nothing would also gut a note reading "marked N/A by the importer". Anything that looks like a code, a flag or an enumeration wants this switch on.

One column narrows the scope. The dropdown lists the file's own headers. Replacing 0 with no across every column of a file with an id column is a memorable mistake; doing it in the active column is a two-second job.

The header row is left alone unless you include it, which is the right default: a search for company should not rename the company column out from under the data. When you do want to rename headers, including the row here works, though the header cleaner is the better tool for it: it prints a before-and-after mapping and it will not let two columns end up with the same name.

Patterns worth keeping

A short list that covers most of what people come to this page for. Switch Pattern on for all of these.

Collapse runs of spaces      find  \s{2,}         replace with a single space
Delete a trailing comma      find  ,\s*$          replace with nothing
Strip a currency symbol      find  ^[$£€]\s*      replace with nothing
Surname first to first last  find  (\w+),\s*(\w+) replace  $2 $1
Digits only                  find  \D             replace with nothing
Mask all but the last four   find  \d(?=\d{4})    replace  *
Normalize a phone prefix     find  ^\+?1[\s-]?    replace with nothing

^ and $ anchor to the start and end of a cell, not of a line, because the search runs cell by cell. That makes the anchored patterns above safe on a file with multi-line values in it.

One warning about the masking pattern: this page is a text tool, not an anonymizer. Replacing digits with asterisks makes a column unreadable to a person and does nothing about the other columns that identify the same row. If the goal is to share a file safely, salted hashing is the thing to reach for.

What it will not touch

  • Structure. Replacing a comma inside a cell does not create a new column. The file is parsed into cells first and written back out with correct quoting, so a value that gains a comma is quoted on the way out and the CSV stays valid.
  • Types. Every cell is a string from read to write. A replacement that turns 0012 into 12 does so because you asked; nothing reinterprets a value on its own, and no leading zero disappears by itself.
  • Row order. Nothing is sorted, added or removed. The output has the same rows in the same order, so it diffs cleanly against the input.
  • Invisible characters. A search for a normal space will not find a non-breaking space, and neither will find a zero-width character. If a replacement mysteriously matches nothing on cells that look right, run the whitespace cleaner over the file and try again.

Frequently Asked Questions

Is the search a regular expression?

Not unless you switch Pattern on. By default every character is treated literally, so a search for 1.50 finds 1.50 rather than 1x50, and a search for C++ works instead of throwing. Turn the pattern switch on and the box becomes a real regular expression, capture groups and all.

How do I use capture groups in the replacement?

Put brackets around the parts of the pattern you want to keep and refer to them as $1, $2 and so on in the replacement. Finding (\w+), (\w+) and replacing with $2 $1 turns Lovelace, Ada into Ada Lovelace. In literal mode $1 is written out as two characters, and the page tells you when that is what is about to happen.

Why did nothing match?

Usually the letter case, since the search is case-sensitive by default, or the scope being set to a single column that is not the one holding the value. The match count updates as you type, so the answer arrives within a keystroke or two rather than after a download.

What is whole cell matching for?

Normalizing codes and flags. Replacing the cell N/A with nothing is safe; replacing the substring N/A with nothing would also gut a note reading marked N/A by the importer. Anything that looks like an enumeration wants this switch on.

Does it change the header row?

No, unless you include it. A search for company should not rename the company column out from under the data. When renaming headers is the actual goal, the header cleaner is the better page: it prints a before-and-after mapping and will not let two columns end up with the same name.

Can a replacement break the CSV?

No. The file is parsed into cells first, and the output is written with proper quoting, so a cell that gains a comma or a quote mark is escaped correctly and the file still reads back as the same shape.

What do the three counts mean?

Matches found, cells those matches were in, and cells that actually came out different. Matches above cells means some cells contain the term twice. Cells changed below cells matched means the replacement is the same as what was found, which is nearly always a typo.

Is my file uploaded?

No. This page has no upload endpoint. The file is read, searched and rewritten by JavaScript in your own tab, and nothing is kept between visits.

Find it, count it, replace it

Free, no account, no upload. Type the term, watch the count, take the CSV.

Back to find and replace