Удаление целых строк в текстовом файле на основе частичного совпадения строк с помощью Windows PowerShell


22

Поэтому у меня есть несколько больших текстовых файлов, которые мне нужно отсортировать, и удалить все вхождения строк, которые содержат данное ключевое слово. В общем, если у меня есть эти строки:

Это не тест
Это тест
Может быть тест
Определенно не тест

И я запускаю скрипт с 'not', мне нужно полностью удалить строки 1 и 4.

Я пытался с:

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

но он заменяет только «Программу», а не всю строку.

Ответы:


25

Вот что я бы сделал:

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

Строка Снарка делает то же самое, но начинается с загрузки всего файла в массив, что может быть проблематично с большими файлами в памяти.


Я бы посоветовал вам использовать Set-Content вместо Out-File, который имеет дело с необработанными данными и не будет обрезать строки или форматировать объекты.
JasonMArcher

@JasonMArcher Можете ли вы опубликовать пример, используя Set-Content? Я не верю, что Set-Contentэто замена для замены Out-File.
Иэн Сэмюэль Маклин Старейшина

Get-Content .\in.txt | Where-Object {$_ -notmatch 'not'} | Set-Content out.txt Out-File - это в основном Set-Content, но он выполняет ввод через форматирование по умолчанию вместо простого преобразования строк.
JasonMArcher

У меня была точно такая же проблема, и вы отвечаете на 99% того, что мне нужно. Последняя проблема заключается в том, что я запускаю команду в цикле с переменной $ (в вашем примере вместо 'not'). Если я жестко закодирую строку, она отлично работает; но если я использую переменную, это ничего не делает. Есть идеи почему? Я попробовал обе переменные и поместил их в "кавычки"
Стивен Р.

Как это можно изменить, чтобы заменить текст в этих строках
Том

7

Это будет работать:

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

Это просто возвращает одну строку во втором файле с именем True.

Исправление: это просто возвращает одну строку во втором файле, состоящем из 'True'. Может быть, в нем отсутствует «Foreach-Object {$ _», поэтому он запускается один раз в строке? Редактировать: Ну, на самом деле это сейчас не имеет значения, он стер файл, который я надеялся очистить. В любом случае, спасибо за помощь, но мне все еще интересно, какой будет правильная команда, чтобы я мог сделать это в будущем?

1
Это работает для меня с вашими 4 тестовыми строками выше.
Snark

2
никогда не будет перезаписывать исходный файл!
user33788

3
согласился, но я использовал те же имена файлов, что и на оригинальном постере, чтобы облегчить ответ. Он использовал co2.txt для ввода и вывода.
Снарк

0

Вы также можете использовать 'Select-String' с опцией -notmatch:

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

0

Мне просто нужно было заставить это работать и придумал следующее:

$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

Ключевым моментом является то, что для 'Where-Object', использующего блок скрипта (как обозначено фигурными скобками), требуется объявить переменную в событии создания блока скрипта, следовательно,

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

линия.

Структурируя его таким образом, можно создать функцию, передать ей текстовую строку для частичного совпадения, выполнить создание блока сценария с переданным значением и заставить его работать правильно.

Ответы выше не правильно объясняют, как передать значение, которое будет заменено в переменной.


Можете ли вы объяснить (более четко), как это лучше, чем ответ Снарка (гораздо более краткий) ? Пожалуйста, не отвечайте в комментариях; отредактируйте свой ответ, чтобы сделать его более понятным и полным.
Скотт
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.