Patterns: Regular Expressions with -match

A regular expression describes the shape of the text you want, such as two letters, a dash and some digits, and -match tests text against it, $Matches holds what it found, and Select-String uses the same patterns across many files.

Journeyman · PowerShell · Operating System · Updated

After this lesson you can

  • Build a regular expression a piece at a time from \d, +, [ ], ^ and $, and test text against it with -match
  • Get the text a pattern matched, from $Matches after -match or from Select-String's Matches in many files
  • Choose between Select-String, Get-ChildItem -Recurse, Where-Object and -match for a search job

Key takeaways

  • A regular expression describes a shape of text: \d is any digit, + is one or more, [A-Z] is any one letter A to Z.
  • ^ means "starts here" and $ means "ends here"; together they test the whole text.
  • -match answers True or False, and after a True, $Matches[0] holds the text that matched.
  • -match and Select-String ignore capital letters; -cmatch and -CaseSensitive don't.
  • Write patterns in single quotes, so PowerShell leaves $ and \ alone.

The hiking club's treasurer needs every order number from this year's meeting notes for the year-end report. The numbers are all different: TM-48213, TS-30577, FA-1190. You can't search for a word, because there isn't one word they share: "order" finds the lines, not the numbers. Reading the notes and copying each number by hand works until there are fifty. What the order numbers share is a shape: some letters, a dash, then some digits. A regular expression (often shortened to regex, read "REJ-ex") is a way to write a shape like that down. Nearly every programming language understands them, so the same patterns help you check that a form's phone number looks right, pull dates out of a log, or find every email address in an export.

This lesson uses the hiking-club folder from Finding Files: Get-ChildItem -Recurse. If you don't have it, run that lesson's practice-folder lines first.

Does it match? -match

-match (read "matches") is a comparison, like -eq: text on the left, a pattern on the right, and the answer is True or False. A plain word is a pattern too:

'paid order TM-48213' -match 'order'
'paid order TM-48213' -match 'invoice'
True
False

Write patterns in single quotes. Inside double quotes PowerShell reads $ as "the value of", and patterns use $ for something else.

A piece at a time

Build the order number's shape one piece at a time, testing as you go. After a True, PowerShell keeps the text that matched in $Matches[0] (read "dollar matches, zero"):

'paid order TM-48213' -match '\d'
$Matches[0]
True
4

\d (read "backslash D", or "a digit") means any one digit, 0 to 9. It found the first one, the 4. Add + (read "one or more"), which repeats the piece before it as many times as it can:

'paid order TM-48213' -match '\d+'
$Matches[0]
True
48213

Now the letters and the dash. [A-Z] (read "any one letter from A to Z") is a character set: square brackets hold the characters allowed in that one spot. [A-Z]+ means one or more letters, and a - outside the brackets means a real dash:

'paid order TM-48213' -match '[A-Z]+-\d+'
$Matches[0]
True
TM-48213

The whole order number. Read the pattern aloud: "one or more letters, a dash, one or more digits".

The order-number pattern laid over TM-48213 piece by piece: one or more letters from A to Z cover TM, the dash covers the dash, and one or more digits cover 48213, with each piece read aloud underneath

Piece Read it as Matches
\d a digit one of 0 to 9
+ one or more the piece before it, repeated
[A-Z] any one letter A to Z one character from the set
[0-5] any one digit 0 to 5 one character from the set
^ starts here the start of the text
$ ends here the end of the text

Three things to know. -match ignores capital letters, so [A-Z] matches tm too; use -cmatch (case-sensitive match) when capitals matter. A . in a pattern means any character at all, so write \. for a real dot, as in '112\.50'. And a False leaves $Matches as it was, still holding the last True's text, so read it only after a True.

Start and end: ^ and $

^ (read "caret") pins the pattern to the start of the text, and $ to the end. '^Action' finds only lines that begin with "Action". Used together, they test the whole text: is this a member number, all digits and nothing else?

'48213' -match '^\d+



'48213a' -match '^\d+



True
False

Without ^ and $, the second would be True, because 48213a contains digits. With them, every character from start to end has to fit. This is how a sign-up form checks a ZIP code.

Many files at once

Select-String takes the same patterns, so the treasurer's job is one line. Find the notes, then search them for the shape:

Set-Location "$HOME\terminal-practice\hiking-club"
Get-ChildItem -Recurse -Filter '*.txt' | Select-String '[A-Z]+-\d+'
2025\notes\2025-11-meeting.txt:3:Treasurer: paid order TM-20931 (10 trail maps), $45.00
2026\notes\2026-09-meeting.txt:3:Treasurer: paid order TS-30577 (12 club T-shirts), $96.00
2026\notes\2026-10-meeting.txt:3:Treasurer: paid order TM-48213 (25 trail maps), $112.50
2026\notes\2026-10-meeting.txt:6:Action: Marco orders first-aid kits, order FA-1190

Each result has a Matches property holding what the pattern found, and its Value is the text. Ask for it, and you get the order numbers alone:

(Get-ChildItem -Recurse -Filter '*.txt' | Select-String '[A-Z]+-\d+').Matches.Value
TM-20931
TS-30577
TM-48213
FA-1190

Notice what didn't match: first-aid and T-shirts have a dash, but no digits after it. Windows PowerShell 5.1, a Mac and Linux all read these patterns the same way.

Try it. Every meeting note has a "Present:" line. Write a pattern that pulls out Present: 11 with the number, then use it on all the notes.

Check yourself

2 questions to try on the lesson page.

So what

When the thing you're looking for has a shape and not a name, describe the shape. \d, +, [ ], ^ and $ already cover order numbers, member numbers and times, and you'll meet them again in every language you learn.

Key terms

Cheat sheets

Related