Deleting entire lines in a text file based on a partial string match with Windows PowerShell

22

6

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.

Charles

Posted 2010-03-08T21:24:26.243

Reputation:

Answers

25

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.

buti-oxa

Posted 2010-03-08T21:24:26.243

Reputation: 453

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 – 2016-05-20T16:47:31.523

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. – JasonMArcher – 2010-08-17T04:16:30.820

How can this be modified to replace the text on those lines – Tom – 2019-11-06T15:27:51.263

@JasonMArcher Can you post an example using Set-Content? I don't believe that Set-Content is a drop-in replacement for Out-File. – Iain Samuel McLean Elder – 2012-11-24T22:05:14.193

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. – JasonMArcher – 2012-11-24T22:25:41.577

7

This will work:

(Get-Content "D:\Logs\co2.txt") -notmatch "not" | Out-File "D:\Logs\co2.txt"

Snark

Posted 2010-03-08T21:24:26.243

Reputation: 30 147

This just returns a single line in the second file named True. – None – 2010-03-09T04:33:15.047

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?
– None – 2010-03-09T04:47:26.057

1It works for me with your 4 test lines above. – Snark – 2010-03-09T06:24:20.803

2would never have it overwrite the original file! – user33788 – 2010-06-22T16:06:01.527

3agreed, 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 – 2010-06-22T16:54:07.640

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.

Walkabout Tigger

Posted 2010-03-08T21:24:26.243

Reputation: 1

Can you explain (more clearly) how this is any better than Snark’s (much more concise) answer? Please do not respond in comments; [edit] your answer to make it clearer and more complete.

– Scott – 2018-03-22T23:20:15.040

0

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

Select-String 'not' .\input.txt -notmatch | % {$_.Line} | set-content output.txt

E.Z. Hart

Posted 2010-03-08T21:24:26.243

Reputation: 111