Finding & Comparing

How to use regex find and replace on Mac

You can do this with Note My, and you already know regular expressions. What you need is the syntax it accepts, the replacement template, and a clear account of what each option changes about your search.

You want to reorder two fields down a whole file, strip a prefix off four hundred lines, or rename an identifier without catching the six other words it appears inside. You know how to write the pattern. The questions are the boring ones: which syntax does the editor accept, how do you refer to a capture group in the replacement, what do the checkboxes quietly change about your search, and how you check your work before you commit it.

This page answers all four for Note My, with worked patterns you can paste straight in. It all happens on your Mac: nothing is uploaded, there is no account, and the files you search never leave the machine.

Open Find & Replace and turn on Regular Expression

  1. Open the pop-over from the toolbar

    Click the magnifying-glass button in the toolbar — the one whose tooltip reads "Find and replace in the active tab." A pop-over opens under it, anchored to the button.

    The toolbar button is where the regex, scope and replace options live, so that is the one to reach for whenever you are doing more than skimming for a word. It floats over the document rather than pushing it aside, so you can type a pattern, read the count and adjust it with the text still in view.

  2. Tick Regular Expression

    Three checkboxes sit under the fields: Case Sensitive, Whole Word and Regular Expression. Tick the third and your query stops being treated as literal text.

  3. Type the pattern and read the count

    Matches highlight live across the chosen scope as you type, and the status label keeps a running count. Let the number settle, then compare it against what you expected: four hundred matches where you wanted forty is a warning worth heeding. Read the count before you press anything — it is the cheapest check you have, and it costs you a second.

    ↩ steps to the next match, ⇧↩ to the previous, ⎋ closes the pop-over. Closing it wipes the highlights.

  4. Write the replacement using $1

    The replace field is a regex template, not literal text. $1 stands for whatever the first capture group matched, $2 the second, and so on down the groups you wrote.

  5. Replace, or bookmark instead of replacing

    Seven buttons sit below: Find Next, Find Previous, Find All, Bookmark All, Replace, Replace All and Replace in All Files. Replace changes the match in front of you; Replace All sweeps the whole scope.

    Bookmark All puts a bookmark on every matching line instead of touching the text. It is the safe first move when you are not yet sure the pattern is right. The Search menu carries its own Bookmark All Search Matches (⌥⌘B) alongside the rest of the bookmark commands.

Note

The find field keeps a list of your recent searches, with No recent searches shown while it is empty and a Clear Recent Searches item to empty it. Long patterns are worth typing once and then picking off that list.

The syntax you can type

The syntax is the one you already know. Our find and replace accepts the standard regular expression syntax used by most modern tools, so a pattern you wrote somewhere else can usually be pasted in as it stands and behave the way you expect on the first try.

That covers character classes, greedy and lazy quantifiers, alternation, anchors, lookahead and lookbehind, backreferences, non-capturing groups with (?:…), and inline flags written into the pattern itself.

It also means the finer control lives where you can read it: in the pattern. Write an inline flag at the very start of your query and it applies to the whole of it — (?s) to let . cross a line ending, (?m) to make ^ and $ meet every line rather than the whole document, (?x) to lay a long pattern out with whitespace and comments so it stays readable a month later. The three checkboxes cover the everyday cases; the flags cover the rest, and both are visible at a glance. Watch the live count change as you type a flag in: it confirms the switch took effect on the text in front of you, which is a better answer than a tick box can give.

Capture groups and the replacement template

The replace field is a template, so a group you capture on the left can be reassembled in any order on the right. Numbered groups are what to rely on: $1, $2, $3, counting the opening parentheses from left to right in your pattern.

If you want the whole match in the replacement, wrap the entire pattern in one group and use $1. That is one character of extra typing and removes any doubt about what you will get back.

Worked patterns with their replacement templates and what each one does
FindReplace withWhat it does
(\w+), (\w+)$2, $1Swaps two comma-separated fields — surname and forename, key and value.
[ \t]+(?=\n)(empty)Strips trailing spaces and tabs. The lookahead finds the line end without relying on an anchor.
\boldName\bnewNameRenames an identifier without touching oldNameSuffix or myOldName.
\bDEBUG:\s*(empty)Removes a log prefix and the whitespace that follows it.
(\d{4})-(\d{2})-(\d{2})$3/$2/$1Reorders an ISO date into day-first form.
"([^"]*)"'$1'Re-quotes string literals, keeping their contents intact.

Leaving the replace field empty is a legitimate replacement. It deletes every match, and two of the rows above rely on that.

The other half of that rule catches people out: anything the pattern matched but the replacement does not mention disappears as well. If you meant to keep it, capture it.

What the other two checkboxes change

Whole Word adds boundaries you did not write

Whole Word does one precise thing: it asks for a word boundary at each end of whatever you typed. Two consequences follow, and both are worth knowing before you tick it.

The first is good news: your group numbers are untouched. $1 still means the first group you wrote.

The second is the trap. A word boundary only holds where a word character sits on one side of it and a non-word character on the other. A pattern that begins or ends on punctuation — \bDEBUG:, say — is suddenly being asked for boundaries it never wanted, and will fail on any match where the surrounding text does not satisfy them. That is why a pattern which works on its own can stop matching, or start matching a smaller set, the moment you tick the box. With Regular Expression on, leave Whole Word clear and write \b yourself, exactly where you want it.

Case Sensitive is a switch, not something you type

The capitals in your pattern do not make a search case-sensitive on their own. With Case Sensitive unticked, ERROR matches error and Error as well. Tick the box when case matters. You do not need an inline case flag as well.

With Regular Expression off, everything is taken literally

Untick the box and every character in the field stands for itself. Metacharacters lose their power rather than causing an error, so searching for $5.00 or a.b or (int) finds exactly those characters. That is the reason to leave the box clear for ordinary searches: a literal query stays literal, however many metacharacters it contains.

Scope: this file, all tabs, or a whole folder

A segmented control in the pop-over chooses between This File and All Tabs. Beyond the single file sit two distinct tools, and knowing which one to reach for is most of the skill: one takes an edit across everything you have open, the other reads a whole folder to tell you where the work is.

Replace in All Files sweeps every tab open in the window, which makes the tab bar your selection: open the files you want changed, and that is exactly the set that changes. You watch the edit land tab by tab — each one pulses yellow as it is edited and green when it is done — and you finish back on the tab you started from. It is a deliberate way to take one pattern across a dozen files and still watch every edit happen.

Find in Folder (⇧⌘F) searches every text file under a folder you choose, and it carries the same three options under slightly different labels: Match case, Whole word, Regular expression. Results stream in grouped by file; double-click a row to open that file at that line. You can narrow it with glob masks separated by ; or ,, and it skips .git, node_modules, build, .build and DerivedData by default.

Important

Find in Folder reads files and never writes them. It is non-destructive by design, so you can point a rough pattern at a large tree and refine it in safety. When you are happy with it, double-click the rows that matter to open those files, then run the replacement from the pop-over with the change in front of you.

Treat a folder scan as reconnaissance: see which files light up, then open the ones that matter and replace there. Each row shows a compact preview of the line it found, which keeps a long results list readable; double-click the row to read the match in full in the editor, where our large-file engine keeps even a huge file quick to scroll.

Troubleshooting

"Invalid pattern"

An invalid pattern is reported inline: the status label reads "Invalid pattern: …" with the reason spelled out, and you hear a beep. Nothing is searched and nothing is changed, so a half-finished pattern can sit in the field harmlessly while you fix it. The usual causes are an unbalanced parenthesis or bracket, a stray quantifier with nothing to repeat, or a backslash escape that is not a real one.

In Find in Folder the same problem is reported in an alert sheet rather than inline.

The count says "capped"

When a pattern matches an enormous number of places in one document, the status appends "(capped — narrow your query for full count)" to tell you the number shown is no longer exact. Treat it as a verdict on the pattern: a query matching that much of one file is usually matching something you did not mean — a bare ., an unanchored \s*, an alternation with an empty branch. A narrower pattern is safer than a Replace All you cannot verify.

The pattern matches, but nothing happens on Replace

Check the scope control first. A match highlighted in another tab is not in scope if the segmented control reads This File. Check the replace field too — an empty replace field is a deletion, not a no-op, so if the text vanished rather than changing, that is the reason.

My pattern stopped matching when I ticked Whole Word

See above: Whole Word asks for a word boundary at each end of your query, so a pattern that begins or ends on a non-word character is now demanding boundaries the surrounding text may not provide. Untick it and put \b in the pattern where you actually want it.

That is the system find bar, which is handy for skimming to a word. For regular expressions, capture groups, the scope control and the replace template, open the pop-over from the magnifying-glass button in the toolbar — everything on this page lives there. Once it is open, ↩ and ⇧↩ walk the matches without your hands leaving the keyboard.

I ran the wrong Replace All

⌘Z undoes it, the same way it undoes anything else you type. The reliable habit, though, is the one before the mistake: read the running count before you commit, and when the pattern is at all subtle, press Bookmark All first. It is the dry run worth building the habit around — every line the pattern touches picks up a mark and not a character changes, so you can skim the marks, adjust and only then replace. Save before sweeping a file you would hate to lose: our auto-recovery safety net catches what a sudden restart would otherwise take, but a save gives you a point you chose.

I need this same replacement every week

Then make it permanent, and there are two good ways to do that. Reach for our macro recorder — ⌥⌘R to start, ⌥⇧⌘R to stop, ⌥⌘P to play back — so the replacement and the find steps around it become one command you fire at the next file, and a playback undoes in a single press. Or, if the pattern is a cleanup rule rather than a one-off edit, put it in Clean ▸ Edit Removal Rules…. Our cleanup rules keep a saved list of regular expressions you apply in one pass, with per-rule match counts and JSON import and export.

Five habits that make a big sweep safe

  • Read the count first. The running total is the cheapest check you have. If it is an order of magnitude off what you pictured, the pattern is wrong, not the file.
  • Bookmark before you replace. Bookmark All marks every line the pattern touches and edits nothing. Skim the marks, tighten the pattern, and replace once you like what you see.
  • Start narrow and widen. Anchor the pattern to something distinctive, confirm the count, then relax it a piece at a time. It is far easier than working back from four hundred unwanted matches.
  • Scout with Find in Folder. A read-only sweep of the whole tree tells you which files are even involved. Open those and change them deliberately, one considered edit at a time.
  • Keep the ones that recur. A replacement you run every week belongs in our macro recorder, and a standing cleanup pattern belongs in our cleanup rules, where it is saved, named and reusable.

None of this needs a network connection or an account, and nothing you search or replace is sent anywhere. The pattern you type, the files you open and the edits you make stay on your Mac.

Frequently asked questions

Which regular expression syntax does Note My accept?

The standard syntax you already know: character classes, quantifiers, alternation, anchors, lookahead and lookbehind, non-capturing groups, and inline flags written into the pattern. A pattern that works in most modern tools can be pasted straight in.

Does $1 work in the replace field?

Yes. The replace field is a template, so numbered capture groups — $1, $2 and so on — come back as whatever each group matched, in whatever order you write them. To reuse the whole match, wrap the pattern in a group and refer to $1.

How do I open Find & Replace?

Click the magnifying-glass button in the toolbar and the pop-over opens beneath it, carrying the regex, scope and replace options described here. Once it is open the keyboard takes over: ↩ for the next match, ⇧↩ for the previous, ⎋ to close.

How do I take one regex replacement across many files?

Use Find in Folder (⇧⌘F) to see which files your pattern touches, double-click the rows to open them, then run Replace in All Files to sweep every open tab in one go. Folder search itself is read-only by design, so the scouting pass can never change anything by accident.

What does "(capped — narrow your query for full count)" mean?

Your pattern matches so many places in the document that the number shown is no longer exact. Nothing has gone wrong, but the pattern is broader than you probably intended. Narrow it and the count becomes exact again.

Does regex work in the folder search as well?

Yes. The folder-search window carries Match case, Whole word and Regular expression checkboxes of its own. An invalid pattern is reported in a sheet instead of inline.