PowerShell: Match Expression Against Text File Using String-Select

Viewed 75

I'm trying to use Select-String in PowerShell to extract lines from a text document containing entries from a change log. I've included a sample, below.

The PS command Select-String "REAPER.*(19|20)" "d:\reaper 6.x versions.txt" successfully extracts the first line of each log entry (e.g. REAPER v.6.11 - May 24, 2020) but I also need the second line from each entry.

I've tried Select-String "REAPER.*(19|20)\n.*" "d:\reaper 6.x versions.txt" and similar but they return blanks or errors.

Stumped.

REAPER v6.11 - May 24, 2020
The Gone-Away World
Downloads:
Windows (12MB installer)
Windows x64 (13MB installer)
OS X Intel (18MB DMG)
OS X 64-bit Intel (20MB DMG)
OS X 64-bit Intel (20MB DMG, notarized for Catalina)
Linux x86_64 (11MB .tar.xz)
Linux i686 (11MB .tar.xz)
Linux armv7l (9MB .tar.xz)
Linux aarch64 (9MB .tar.xz)
Changes:
Appearance: add Theme Color Controls window for per-theme brightness/contrast/gamma/color adjustment



REAPER v6.10 - May 9, 2020
The Gone-Away World
Downloads:
Windows (12MB installer)
Windows x64 (13MB installer)
OS X Intel (18MB DMG)
OS X 64-bit Intel (20MB DMG)
OS X 64-bit Intel (20MB DMG, notarized for Catalina)
Linux x86_64 (11MB .tar.xz)
Linux i686 (11MB .tar.xz)
Linux armv7l (9MB .tar.xz)
Linux aarch64 (9MB .tar.xz)
Changes:
ARA: preserve edits when user applies timing changes to media or imports as MIDI

2 Answers

You can use

PS> Get-Content "d:\reaper 6.x versions.txt" -Raw | Select-String "REAPER.*(?:19|20)(?:\r?\n.*)?" -AllMatches | Foreach-Object { $_.Matches.Value }
REAPER v6.11 - May 24, 2020
The Gone-Away World
REAPER v6.10 - May 9, 2020
The Gone-Away World

NOTE:

  • Get-Content $file -Raw will read in the whole file as a single string, not an array of lines, so that the pattern could match multiple lines within one match operation
  • REAPER.*(?:19|20)(?:\r?\n.*)? pattern will match from REAPER till the 19 or 20 and then an optional sequence of a CRLF or LF line ending and any zero or more chars other than a newline.

See the regex demo online.

To output the two adjacent lines as two columns for output to a CSV, you may use

Get-Content "d:\reaper 6.x versions.txt" -Raw | 
  Select-String "(REAPER.*(?:19|20))(?:\r?\n([^\r\n]*))?" -AllMatches | 
    Foreach {$_.Matches} | 
      Foreach { new-object psobject -Property @{Tool=$_.Groups[1];Name=$_.Groups[2]} } |
        Select Tool,Name | 
         Export-Csv  -NoTypeInformation "d:\reaper 6.x versions.csv"

Output:

"Tool","Name"
"REAPER v6.11 - May 24, 2020","The Gone-Away World"
"REAPER v6.10 - May 9, 2020","The Gone-Away World"

How about using -context? 0 lines before, 1 after:

Select-String "REAPER.*(19|20)" file.txt -Context 0,1

> file.txt:1:REAPER v6.11 - May 24, 2020
  file.txt:2:The Gone-Away World
Related