Puzzled
Puzzled

Reputation: 13

Powershell Foreach construction remove text in multiple files

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?

Upvotes: 1

Views: 193

Answers (1)

Santiago Squarzon
Santiago Squarzon

Reputation: 60120

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)
}

Upvotes: 1

Related Questions