1

As newby to powershell I googled a long time to make a piece that can remove a part of text in a single file based upon some variables like this. The text section can be anywhere within the file. And that specific section needs to be removed.

<#
#create test file
$file = "c:\users\public\Test\remove.txt"
Set-Content $file (1..100) -Force
$content = Get-Content $file
#>
$file = Get-Content "c:\users\public\Test\remove.txt"
$StartText= '50'
$EndText= "75"
$LineNumberStart= $file | Select-string -Pattern $StartText
$Start = $linenumberStart.LineNumber
$LineNumberEnd= $file | Select-string -Pattern $EndText
$End = $linenumberEnd.LineNumber
$keep = $file[0..$Start] + $file[$End..($file.Count - 1)]
$keep | Set-Content "c:\users\public\test\remove.txt"

Now I would like have to the above working functionality but on all files in a particular folder. However, for the reason "Expressions are only allowed as the first element of a pipeline." I can't get it to work with this piece of code below:

$ReportPath = Split-Path -Parent $Script:MyInvocation.MyCommand.Path
$StartText= "50"
$EndText= "75"
Get-ChildItem -Path $ReportPath -Filter *.txt | ForEach {  (Get-Content $_.PSPath) | 
$LineNumberStart= $_ | Select-string -Pattern $StartText
$Start = $LineNumberStart.LineNumber
$LineNumberEnd= $_ | Select-string -Pattern $EndText
$End = $LineNumberEnd.LineNumber
$keep = $_[0..$Start] + $_[$End..($_.Count - 1)]
$keep|Set-Content $_.PSPath
}

Expected outcome is that all files in the folder have the middle section of the text file removed.

Can someone please assist in getting this foreach construction resolved?

2
  • (Get-Content $_.PSPath) | followed by a variable assignment on next line is a syntax error. The | should not be there as it seems Commented Apr 13, 2022 at 23:36
  • Removing the "|" eliminated the error received, but now the entire content of the file is truncated. That was not the goal of the script. It should only remove a section of the text, not everything. Any other improvements to be made? Commented Apr 13, 2022 at 23:50

1 Answer 1

1

I would recommend you to use a switch for this use case, if I understand correctly you're looking to start skipping the lines of a file from where the line matches the value of $StartText and stop skipping after the line matches the value of $EndText. If that's the case, here is a minimal example of how you can do this using a switch statement with the -Regex parameter:

$StartText = '50'
$EndText = '75'
$skip = $false

switch -Regex (0..100) {
    $StartText { $skip = $true; continue }
    $EndText { $skip = $false; continue }
    { $skip } { continue }
    default { $_ }
}

If this is what you expected, then if you want to the same for each file, the code would look like this, note the use of -File to read each file content:

$StartText = '50'
$EndText = '75'
$skip = $false

Get-ChildItem -Path $ReportPath -Filter *.txt | ForEach-Object {
    & {
        switch -Regex -File ($_.FullName) {
            $StartText { $skip = $true; continue }
            $EndText { $skip = $false; continue }
            { $skip } { continue }
            default { $_ }
        }
    } | Set-Content ($_.BaseName + '-New' + $_.Extension)
}
Sign up to request clarification or add additional context in comments.

2 Comments

Thank you that works with a slight modification on the set-content line. Modified it to "set-Content "$($_.PSPath)-new" . This to avoid the error message that the file is open by another process. It creates a new file instead though.
@Puzzled that's a good catch, happy to help ;)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.