1

I've been through so many posts today that offer Powershell examples of how to remove entire lines from a file by using line numbers. Unfortunately none of them do quite what I need, or they have some 'but' type clauses in them.

The closest example I found uses the -remove method. This managed to do the job, until I noticed that not all lines that I was trying to remove, were removed. After some more research I found that -remove is reliant on Regex and Regex does not like certain special characters which happen to be in some of the lines I wish to delete/remove.

The example I'm using is not my own work. user2233949 made it (cheers buddy) I found it very simple though, so I made it into a Function:

Function DeleteLineFromFile ($Path, $File, $LineNumber){
        $Contents = Get-Content $Path\$File
        $Contents -replace $Contents[$LineNumber -1],"" | Set-Content $Path\$File
        }

A great example I reckon. Only regex won't work with the special chars.

The goal is this: To make a function that doesn't care about what is in the line. I wan't to feed it a path, file and line, then have the function delete that line and save the file.

1 Answer 1

1

This is fairly easy and does not need regex at all.

Read the file:

$lines = Get-Content $Path\$File

We then have an array that contains the lines in the file. When we have an array we can use indexes to get elements from the array back, e.g.

$lines[4]

would be the fifth line. You can also pass an array into the index to get multiple lines back:

$lines[0,1,5]   # returns the first, second and 6th line
$lines[0..5]    # returns the first 6 lines

We can make use of that with a little trick. PowerShell's comparison operators, e.g. -eq work differently with an array on the left side, in that they don't return $true or $false, but rather all elements from the array matching the comparison:

1..5 -ge 3      # returns 3,4,5
0..8 -ne 7      # returns 0 through 8, *except* 7

You probably can see where this is going ...

$filteredLines = $lines[0..($lines.Length-1) -ne $LineNumber - 1]

Technically you can ignore the - 1 after $lines.Length because indexing outside of an array simply does nothing. This does actually remove the line you want to remove, though. If you just want it replaced by an empty line (which your code seems to be doing, but it doesn't sound like that's what you want), then this approach won't work.

There are other options, though, e.g. with a ForEach-Object:

Get-Content $Path\$File |
  ForEach-Object { $n = 1 } {
    if ($n -ne $LineNumber) { $_ } else { '' }
  }

A word of advice on writing functions: Usually you don't have separate $Path and $File parameters. They serve no real useful purpose. Every cmdlet uses only a $Path parameter that points to a file if needed. If you need the folder that file resides in, you can always use Split-Path -Parent $Path to get it.

Sign up to request clarification or add additional context in comments.

3 Comments

Hi Joey. Thanks for the help. When I use your ForEach-object example and pipe the results to Out-File or Set-Content.. I get an error advising that
Hi Joey. Thanks for the help. When I use your ForEach-Object example and pipe the results to Out-File or Set-Content... I get an error advising that an empty pipe element is not allowed. Can you show me a full example on how you would form this function and have it pipe the results out to Set-Content?
Hi Again, never mind. I figured the Set-Content issue out. But using your method, I still can't seem to get the lines to delete...

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.