Powershell 从包含大量字符串的大文本文件中删除任何行

Powershell remove any lines from big text file containing any of a large number of strings

我们有一个很大的 (~100MB) 文本文件。 我们需要删除包含某些短语的任何行。我想使用 PowerShell 来替换当前的方法,它使用 windows grep 并且是一个 .bat 文件。

问题是,大约有 95 个关键短语。必须删除包含任何这些短语的任何行。

关键短语列表包含在 "badPhrases.txt" 中,行与常规文本文件一样分隔。大约有 100 个,我不想将它们包含在硬编码列表中,但如果必须的话,我会的。

我尝试了 couple/few 比较,但我的输出总是比原始输入文件大!或者,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}

我搜索了 Whosebug 并四处搜索,但我找不到任何 link 没有死的,可以解决这个确切的用例。有一个 "hey scripting guy" 参考,但是...... link 已经死了。

使用 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+ 中,默认更明智的是 BOM-less 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 默认匹配 entire LHS;匹配 substring[= LHS 的 91=],您必须将 * 放在 RHS 的两端。)

有关详细信息,请参阅

$arrayFromFile -notin $_

$_ -notcontains $arrayFromFile

原则上,您必须 反转 containment operators -in and -contains 的操作数及其否定 - 语法为 <array> -contains <value><value> -in <array> - 但问题是,整个字符串的匹配是通过任何一种方式执行的,所以这种方法只有在$arrayFromFile包含完整行时才有效 出现在输入中(-in-contains 隐式执行每个元素 -eq 比较)。