Get-Content being treated as a single line by Select-String?

This topic contains 5 replies, has 2 voices, and was last updated by Profile photo of Dave Wyatt Dave Wyatt 9 months ago.

  • Author
    Posts
  • #35908
    Profile photo of James Booth
    James Booth
    Participant

    Hi again guys,

    I never realised how pain-staking parsing plain text can be after the luxury of using objects for so long. Basically, I'm trying to rip out some of the comment-based help from my Powershell documents and I'm going to feed it into my Readme.md.

    So, I have my .PS1 file that I'm using Get-Content on, saving to $FileContents, splitting it up via. regex and then using 'Select-String -Pattern '@' -SimpleMatch -Raw' (I added the -Raw after reading Why Get-Content aint yer friend.

    On the match results, the first line underneath .SYNOPSIS will be '@MyFunctionName' so that I can tell what each comment-based help is for, but I might alter this later.

    EDIT: The code sample broke formatting on the post so I've moved it to pastebin

    I just piped it to Format-List for testing, but it looks like it's treating my strings as a single line (even though they contain line break characters) as the returned result's .LineNumber property returns 1.

    I've also tried running the Select-String on the initial $FileContents variable and it seems to do the same. I've tried splitting my $FileContents with .Split("`n") and piping that through, but the only way I can make int work is to use

    [System.IO.File]::ReadAllLines("D:\TestFile.ps1") | Select-String...
    

    But I have to pipe it directly into my Select-String command – saving it to a variable just results in the same issue.

    I had previously used .Split("`n") and looped through each line but I assumed using Select-String would be more speed efficient (and more 'PowerShell'), but so far I can't get it to work!

    Any ideas?

  • #35919
    Profile photo of Dave Wyatt
    Dave Wyatt
    Moderator

    The [regex]::Matches method takes a string as its first parameter, and you've passed it an array of strings. PowerShell automatically makes the conversion for you, by joining the strings with the output separator (a space, by default).

    If you want to use that .NET method, you'll need to loop over the lines yourself before calling [regex]::Matches

  • #36003
    Profile photo of James Booth
    James Booth
    Participant

    I realised my error in the regex bit, but now I've gone back to the start and I'm just generally fighting with Get-Content & Select-String together.

    What is confusing me is, if I do the following...

    [string]$FileContents = Get-Content "D:\TestFile.ps1" | Out-String
    
    PS D:\Powershell> $FileContents.GetType()
    
    IsPublic IsSerial Name                                     BaseType                                         
    -------- -------- ----                                     --------                                         
    True     True     String                                   System.Object                                    
    
    PS D:\Powershell> $FileContents | Measure-Object -Line
    
    Lines Words Characters Property
    ----- ----- ---------- --------
      227       
    
    

    And if I $FileContents.Replace("`r`n",'!') it removes all of the line breaks and swaps them with an exclamation mark.

    Am I missing something in how each line is treated as a new line? Am I not really dealing with a string here?

    I have no issues if I use the -Path parameter on Select-String, or if I pipe directly from Get-Content into Select-String, so it would seem that it's getting b0rked at some point when I save the content into a variable.

    Apologies if I'm missing something or misunderstanding, but it's been a long day and I'm spending too long on this issue, not for a functional reason as I have working code for this, but purely out curiosity/frustration/stubbornness!

    Thanks for your help so far.

  • #36004
    Profile photo of Dave Wyatt
    Dave Wyatt
    Moderator

    Again you've forced your file contents to be a single string, by piping it to Out-String (and also declaring your $FileContents variable as a [string] type). If you want to have an array of lines, which Get-Content gives by default, then you'd just do this:

    $FileContents = Get-Content 'D:\TestFile.ps1'
    
  • #36019
    Profile photo of James Booth
    James Booth
    Participant

    So, I've been going about this all wrong?!

    I think I misunderstood a little from your original postl; I thought you were saying the InputObject must NOT be an array, so I've been trying my hardest to force the output to be a single string containing line break characters. I'm testing it now with an array of strings and it's working flawlessly. I guess this is good lesson about how some cmdlets parse 'flat text' too.

    Thanks for the help yet again Dave

  • #36020
    Profile photo of Dave Wyatt
    Dave Wyatt
    Moderator

    What I originally meant was that you shouldn't use [regex]::Matches() on the entire file contents if you want to do things on each line individually.

You must be logged in to reply to this topic.