Sh3perd
Sh3perd

Reputation: 89

how to grab a substring between a character and a string in powershell using regex

I have a variable $s that holds a filepath and an error based on piping a get-childitem to selecting a pattern in a string. the output looks something like this:

C:\Users\admin\Desktop\testpoint.txt:15906:  Error: an error has been logged.

where

$s = C:\Users\admin\Desktop\testpoint.txt:15906:  Error: an error has been logged.

Now what I want to do is select the string between \ and .txt (IE, the output in this example is testpoint) and output it as a secondary variable. 'regex::Matches' is what will allow me to do this from what I have researched, but the syntax is what is killing me. so far this is what i attempted:

 [regex]::Matches($s, '\([^/)]+).txt')

but, it errors out. How do I go about getting whatever is between two constraints, in this case the constraints being the character " \ " and the string ".txt?"

Upvotes: 2

Views: 743

Answers (2)

mklement0
mklement0

Reputation: 440162

An alternative is to use a single -replace operation:

PS> $s = 'C:\Users\admin\Desktop\testpoint.txt:15906:  Error: an error has been logged.'
    $s -replace '^.+\\([^.]+)\..+$', '$1'
testpoint

But, as Mathias R. Jessen points out, it's probably easier to extract this information via properties from the Microsoft.PowerShell.Commands.MatchInfo objects output by Select-String, which your sample output suggests you're dealing with, along the lines of:

PS> Select-String -List 'Error:' *.log | Split-Path -LeafBase
testpoint
  • -List limits the searches to at most 1 match per file.
  • The MatchInfo output objects have a .Path property reflecting the path of the file in which a match was found, and that property binds to Split-Path's -Path parameter via the pipeline.

Note: The -LeafBase parameter of the Split-Path cmdlet requires PowerShell (Core) v7+, and isn't supported in Windows PowerShell; there you can use:

PS> Select-String -List 'Error:' *.log | ForEach-Object {
      [IO.Path]::GetFileNameWithoutExtension($_.Path)
    }
testpoint

Upvotes: 1

Wiktor Stribiżew
Wiktor Stribiżew

Reputation: 627409

You can use

[regex]::Match($s, '[^\\]+(?=\.txt)').value

The regex will match

  • [^\\]+ - one or more chars other than \
  • (?=\.txt) - that are immediately followed with .txt.

See the .NET regex demo.

Another idea: cut at the second : and parse the file name without extension:

[io.path]::GetFileNameWithoutExtension(($s -replace '^([^:]*:[^:]*):.*', '$1'))

See this regex demo. Details:

  • ^ - start of string
  • ([^:]*:[^:]*) - Group 1: zero or more chars other than :, a :, and again zero or more chars other than :
  • : - a : char
  • .* - the rest of the string.

Upvotes: 2

Related Questions