27

So I have several large text files I need to sort through, and remove all occurrences of lines which contain a given keyword. So basically, if I have these lines:

This is not a test
This is a test
Maybe a test
Definitely not a test

And I run the script with 'not', I need to entirely delete lines 1 and 4.

I've been trying with:

PS C:\Users\Admin> (Get-Content "D:\Logs\co2.txt") | 
Foreach-Object {$_ -replace "3*Program*", ""} | 
Set-Content "D:\Logs\co2.txt"

but it only replaces the 'Program' and not the entire line.

4 Answers 4

31

Here's what I would do:

Get-Content .\in.txt | Where-Object {$_ -notmatch 'not'} | Set-Content out.txt

Snark's line does the same, but it starts with loading all of the file into an array, which may be problematic with big files memory-wise.

5
  • I would suggest that you use Set-Content instead of Out-File, the former deals in raw data and won't cut off strings or format objects. Aug 17, 2010 at 4:16
  • @JasonMArcher Can you post an example using Set-Content? I don't believe that Set-Content is a drop-in replacement for Out-File. Nov 24, 2012 at 22:05
  • Get-Content .\in.txt | Where-Object {$_ -notmatch 'not'} | Set-Content out.txt Out-File is basically Set-Content, but it runs the input through the default formatting instead of simple string conversion. Nov 24, 2012 at 22:25
  • I had the exact same problem and you answer is 99% of what I need. The final issue is that I'm running the command in a loop with a $variable (replacing 'not' in your example). If I hard code a string it work perfectly; but if I use a variable it does nothing. Any idea why? I've tried both the bare variable and putting it in "quotes"
    – Stephen R
    May 20, 2016 at 16:47
  • How can this be modified to replace the text on those lines
    – Tom
    Nov 6, 2019 at 15:27
9

This will work:

(Get-Content "D:\Logs\co2.txt") -notmatch "not" | Out-File "D:\Logs\co2.txt"
5
  • This just returns a single line in the second file named True.
    – Charles
    Mar 9, 2010 at 4:33
  • Correction: This just returns a single line in the second file consisting of 'True'. Is it maybe missing the "Foreach-Object {$_ " so it runs once per line? Edit:Well actually it's irrelevant now, it erased the file I was hoping to clear up. Thank you for the help anyway, but I'm still curious what the correct command would be so I can do this in the future?
    – Charles
    Mar 9, 2010 at 4:47
  • 1
    It works for me with your 4 test lines above.
    – Snark
    Mar 9, 2010 at 6:24
  • 2
    would never have it overwrite the original file!
    – user33788
    Jun 22, 2010 at 16:06
  • 3
    agreed, but I used the same filenames as used by the original poster, to make the answer easier. He used co2.txt for both input and output.
    – Snark
    Jun 22, 2010 at 16:54
1

You could also use 'Select-String' with the -notmatch option:

Select-String 'not' .\input.txt -notmatch | % {$_.Line} | set-content output.txt
1
  • Good stuff. This worked for me, and the output file was also much smaller in size compared to the "Get-Content" based solutions in other answers. Oct 2, 2023 at 4:38
0

I just needed to get this working and came up with the following:

$InServerName = 'SomeServerNameorIPAddress'
$InFilePath = '\Sharename\SomePath\'
$InFileName = 'Filename.ext'

$OutServerName = 'SomeServerNameorIPAddress'
$OutFilePath = '\Sharename\SomePath\'
$OutFileName = 'Filename.out'

$InFile = -join('\\',$InServerName,$InFilePath,$InFilename)
$OutFile = -join('\\',$OutServerName,$OutFilePath,$OutFilename)
$FindStr = 'some string to match on'
$CompareStr = [scriptblock]::Create($FindStr)
$CompareStr
Get-Content $InFile | Where-Object {$_ -notmatch $CompareStr} | Set-Content $OutFile
Get-Content $OutFile

The key being that the 'Where-Object' using a script block (as denoted by the curly braces) requires declaring the variable in a script block creation event, hence the

$CompareStr = [scriptblock]::Create($FindStr)

line.

By structuring it in this way, one can create a function, pass it a text string to partially match, perform the script block creation with the passed value, and have it work correctly.

The answers above do not correctly explain how to pass the value to be replaced within a variable.

1

You must log in to answer this question.