Powershell удаляет любые строки из большого текстового файла, содержащего любую из большого количества строк - PullRequest
1 голос
/ 08 января 2020

У нас есть большой (~ 100 МБ) текстовый файл. Нам нужно удалить все строки, которые содержат определенные фразы. Я хотел бы использовать PowerShell для замены текущего метода, который использует windows grep и является файлом .bat.

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

Список ключевых фраз содержится в "badPhrases.txt", строка разделена как обычный текстовый файл. Их около 100, я не хочу включать их в жестко запрограммированный список, но я сделаю это, если придется.

Я пробовал пару / несколько сравнений, но мой вывод всегда БОЛЬШЕ, чем мой оригинальный входной файл! Или 0k (пусто). Что я делаю неправильно? Я подозреваю, что проблема в фильтре Where-Object, но я могу ошибаться.

[string[]]$arrayFromFile = Get-Content -Path '.\badPhrases.txt'
get-content ".\inputfile.txt" | Where-Object {$_ -notlike $arrayFromFile} | Out-File ".\clean_data.txt" -Force

Я пробовал -notlike, -notin -notmatch и -notcontains (при переворачивании массива и объекта ввода вокруг таким образом, что казалось логичным). Например ...

Where-Object {$arrayFromFile -notin $_}
....
Where-Object {$_ -notcontains $arrayFromFile}
....
Where-Object {$_ -notlike arrayFromFile}

Я искал stackOverflow и гуглил вокруг, и я не могу найти ни одной ссылки, которая не является мертвой, которая касается именно этого варианта использования. Была ссылка "Эй, парень сценариев", но ... ссылка была мертва.

1 Ответ

1 голос
/ 08 января 2020

Использовать Select-String, который поддерживает несколько критериев поиска через массив строк, передаваемых его параметру
-Pattern:

Select-String -NotMatch -SimpleMatch -Pattern (Get-Content -Path .\badPhrases.txt) .\inputfile.txt |
 Select-Object -ExpandProperty Line | 
   Out-File .\clean_data.txt -Force

Кодировка символов предостережение: В Windows PowerShell Out-File по умолчанию создает файлы Unicode (UTF-16LE), где каждый символ представлен (как минимум) 2 байтами; в PowerShell [Core] 6+ по умолчанию используется более разумный UTF-8 без спецификации; используйте параметр -Encoding для явного управления кодировкой символов.

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

  • -SimpleMatch обеспечивает сопоставление шаблонов буквально со строками входного файла; по умолчанию они интерпретируются как регулярные выражения.

  • Обратите внимание, что сопоставление по умолчанию не учитывает регистр ; при необходимости используйте -CaseSensitive.

  • Поскольку Select-String выводит Microsoft.PowerShell.Commands.MatchInfo экземпляров по умолчанию, Select-Object -ExpandProperty Line требуется для извлечения самих строк.

    • Примечание. В PowerShell 7+ вместо него можно использовать переключатель Select-String -Raw.

Что касается что вы пытались :

$_ -notlike $arrayFromFile

Вы не можете использовать массив в качестве RHS операторов сравнения строк, таких как как -like, -match, -eq - вы можете сопоставлять только одну строку за раз.

(Кроме того, -like / -notlike соответствует вся LHS по умолчанию; чтобы соответствовать подстроке LHS, вам нужно поставить * на любом конце RHS.)

См. этот ответ для получения дополнительной информации.

$arrayFromFile -notin $_

$_ -notcontains $arrayFromFile

В принципе, вам придется реверс операнды для операторов удержания -in и -contains и их отрицания - Синтаксис <array> -contains <value> и <value> -in <array> - но проблема в том, что, опять же, сопоставление целых строк выполняется в любом случае, так что этот подход будет работать, только если $arrayFromFile содержит full строки присутствуют на входе (-in и -contains неявно выполняют сравнения для каждого элемента -eq).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...