19

I am trying to get a string of text from a .sln (Visual Studio solution file) to show what project files are contained within the solution.

An example line of text is

Project("{xxxx-xxxxx-xxxx-xxxx-xx}") = "partofname.Genesis.Printing", "Production\partofname.Genesis.Printing\partofname.Genesis.Printing.csproj", "{xxx-xxx-xxx-xxx-xxxx}" EndProject

The part of the string that I am interested in is the last part between the \ and the ".

\partofname.Genesis.Printing.csproj"

The regular expression I am using is:

$r = [regex] "^[\\]{1}([A-Za-z.]*)[\""]{1}$"

I am reading the file content with:

$sln = gci .\Product\solutionName.sln

I don't know what to put in my string-select statement.

I am very new to PowerShell and would appreciate any and all help...

I did have a very very long-hand way of doing this earlier, but I have lost the work... Essentially it was doing this for each line in a file:

Select-String $sln -pattern 'proj"' | ? {$_.split()}

But a regular expression would be a lot easier (I hope).

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Simon Price
  • 455
  • 2
  • 6
  • 17

3 Answers3

31

The following gets everything between " and proj":

Select-String -Path $PathToSolutionFile ', "([^\\]*?\\)*([^\.]*\..*proj)"' -AllMatches | Foreach-Object {$_.Matches} | 
       Foreach-Object {$_.Groups[2].Value}

The first group gets the folder that the proj file is in. The second group gets just was you requested (the project file name). AllMatches returns every match, not just the first. After that it's just a matter of looping through each collection of matches on the match objects and getting the value of the second group in the match.

Swoogan
  • 5,298
  • 5
  • 35
  • 47
  • I get `partofname.Genesis.Printing\partofname.Genesis.Printing.csproj` and not `Production\partofname.Genesis.Printing\partofname.Genesis.Printing.csproj` that I expected which is the part between " and proj". Can you explain what the corner brackets do, are they quantifiers? `^` means `not` and `?` is zero or one.`.` is any char and `*` is zero or more. – Timo Jul 03 '21 at 19:57
  • @Timo the second group doesn't get everything in the quotes. It only gets the project file name. But there was actually an error in the expression. The second `?` should have been a `+` or `*`. Various online resources can explain the regex components much better than I can in a comment. – Swoogan Jul 04 '21 at 21:43
7

Your Script works great. To make into a one liner add -Path on the Select String:

Select-String -path $pathtoSolutionFile ', "([^\\]*?\\)?([^\.]*\..*proj)"' -
AllMatches | Foreach-Object {$_.Matches} | Foreach-Object {$_.Groups[2].Value}

To build from this you can use Groups[0]

(((Select-String -path $pathtoSoultionFile ', "([^\\]*?\\)?([^\.]*\..*proj)"' -AllMatches | Foreach-Object {$_.Matches} | 
       Foreach-Object {$_.Groups[0].Value})-replace ', "','.\').trim('"'))
Thom Schumacher
  • 1,469
  • 13
  • 24
  • 1
    "_To make into a one liner_" confused me briefly (who hadn't made it a one-liner?) until I discovered [the accepted answer was edited to match this one after this answer was posted](https://stackoverflow.com/posts/26891936/revisions). Nbd, but makes more sense now. – ruffin Dec 20 '22 at 21:29
1

For me this pattern was the best: [^"]+\.csproj

BLuM
  • 657
  • 5
  • 28