Public/Common/Search-FileContent.ps1

function Search-FileContent
{
    [CmdletBinding()]
    param
    (
        # The path to the file to read
        [Parameter(Mandatory = $true)]
        [string]
        $FilePath,

        # The header/beginning/first line that indicates the block of text you want to return.
        [Parameter(Mandatory = $true)]
        [string]
        $StartStringPattern,

        # Where to stop searching
        [Parameter(Mandatory = $false)]
        [string]
        $StopStringPattern,

        # Returns a string instead of an array
        [Parameter(Mandatory = $false)]
        [switch]
        $AsString
    )
    
    begin
    {
        
    }
    
    process
    {
        try
        {
            $FileContentArray = Get-Content $FilePath -ErrorAction 'Stop'
        }
        catch
        {
            throw "Failed to read file '$FilePath'.`n$($_.Exception.Message)"
        }

        $TextToReturn = $null
        $LineCount = 0
        $StartStringLine = $null
        $StopStringLine = $null
        $StartOffset = 1
        $StopOffset = -1
        # If there's not stop string pattern we assume the user wants to get the entire rest of the file, so we go until the last line
        if (!$StopStringPattern)
        {
            Write-Debug 'No stop string provided, using end of file'
            $StopStringLine = $FileContentArray.Count
            $StopOffset = 0
        }

        $FileContentArray | ForEach-Object {
            $Line = $_.Trim()
            $LineMatch = $null
            # Have disabled the below debugging, it's very very verbose 😬
            # Write-Debug "Line: $LineCount`nContents:$Line"
            if (-not $StartStringLine)
            {
                $LineMatch = [regex]::Match($Line, $StartStringPattern)
                if ($LineMatch.Success)
                {
                    Write-Verbose "Found match to '$StartStringPattern' on line $LineCount"
                    $StartStringLine = $LineCount
                }
            }
            if ($StopStringPattern)
            {
                if (-not $StopStringLine)
                {
                    $LineMatch = [regex]::Match($Line, $StopStringPattern)
                    if ($LineMatch.Success)
                    {
                        Write-Verbose "Found match to '$StopStringPattern' on line $LineCount"
                        $StopStringLine = $LineCount
                    }
                }
            }
            $LineCount++
        }

        # We make the concious decision to fail if the string is not found, this is because anything calling this cmdlet is expecting to find something
        if (-not $StartStringLine)
        {
            throw "Failed to find '$StartStringPattern' in file at '$FilePath'."
        }
        if ($StopStringPattern)
        {
            if (-not $StopStringLine)
            {
                throw "Failed to find '$StopStringPattern' in file at '$FilePath'."
            }
        }
        # We want to get the line after the starting string
        $TextBlockStartLine = $StartStringLine + $StartOffset
        # And either the line before the stop string or the last line of the file depending on what we're doing
        $TextBlockStopLine = $StopStringLine + $StopOffset

        try
        {
            # There may be cases where there's no text between the start and end so they'll be on the same line
            if ($TextBlockStartLine -ne $TextBlockStopLine)
            {
                $TextToReturn = $FileContentArray[$TextBlockStartLine..$TextBlockStopLine]
                if (!$TextToReturn)
                {
                    Write-Error 'Failed to get text to return.'
                }
            }
        }
        catch
        {
            throw "Failed to extract text.`n$($_.Exception.Message)"
        }
    }
    
    end
    {
        if ($TextToReturn)
        {
            if ($AsString)
            {
                return [String]$TextToReturn
            }
            else
            {
                return $TextToReturn
            }
        }
        else
        {
            return $null
        }
    }
}