使用 PowerShell 从文本文件中删除多个特定行

Delete multiple, specific lines from text file using PowerShell

我正在使用 powershell 脚本来编辑从 registry.pol 生成的文本文件。最终目标是实现 CIS L1 基准。为了使 CIS L1 按照 this link 中的描述在 AWS EC2-image-builder 中工作,需要删除以下部分:

Computer
Software\Policies\Microsoft\Windows NT\Terminal Services
fPromptForPassword
DWORD:1

Computer
Software\Policies\Microsoft\WindowsFirewall\PublicProfile
AllowLocalPolicyMerge
DWORD:0

Computer
Software\Policies\Microsoft\WindowsFirewall\PublicProfile
AllowLocalIPsecPolicyMerge
DWORD:0

到目前为止,这是我的代码,用于将所有内容 但是 这 3 个部分传输到输出文件:

Get-Content -Path C:\MS-L1.txt -Raw | where -notmatch {
  if( $_.StartsWith("Computer") ) {
    $section = select-string -pattern Computer -context 0,3
    if( ($section -like "fPromptForPassword") and ($section -like "AllowLocalPolicyMerge") and ($section -like "AllowLocalIPsecPolicyMerge") ){
    }
  } | Out-File c:\MS-L1.txt

我想弄清楚如何 select 某些第一行是“计算机”的部分,而不是 所有 第一行是“计算机”的部分,仅当“计算机”后面的行也匹配需要删除的内容时:

  1. 在一行中检查“计算机”

  2. 将当前行和接下来的 3 行存储为一个部分

  3. 检查唯一注册表设置部分(即 fPromptForPassword)

  4. 重复第 2 部分(从“计算机”开始)

  5. 重复第 3 部分“”

  6. 将剩余的(unselected)输出通过管道传输到 MS-L1.txt

我相信使用 -context 检查“computer”之后的 3 行是可行的,但我对我的嵌套 if 语句的格式没有信心,感谢您的指导!

由于您使用 Get-Content -Raw 来完整读取输入文件,因此使用单个 操作效率更高:

(Get-Content -Raw C:\MS-L1.txt) -replace '(?m)^Computer\r?\n.+\r?\n(?:fPromptForPassword|AllowLocalPolicyMerge|AllowLocalIPsecPolicyMerge)\r?\n.+(?:\r?\n)?'

注意:如果您知道自己总是在处理 CRLF 换行符(Windows 样式),则可以使用 \r\n 而不是 \r?\n;如果你总是处理 LF 换行符(Unix 风格),\n 就可以了。

有关上面使用的正则表达式的解释,包括对其进行试验的能力,请参阅 this regex101.com page


至于你试过的

语法问题:

您的 Where-Object (where) command mixes simplified syntax 传递了 脚本块 ,这是不支持的;在摘要中你有两个选择:

  • 简化语法:... | where someProperty -notmatch $someRegex

    • 请注意,隐式操作输入对象 作为一个整体 而不是对其 属性之一 进行隐式操作 - 不幸的是 - 不支持PowerShell 7.2,但 GitHub issue #8357 建议在将来修复该问题。通过此增强功能,您可以执行 1..5 | Where -gt 2 之类的操作,但目前该操作失败。
  • 脚本块语法:... | where { $_.someProperty -notmatch $someRegex }

概念问题:

  • 您的命令被设计为 面向行的 (尽管您必须删除 -Raw 开关才能实际发送输入文件的通过管道 一条一条 行),因此您需要跟踪 Where-Object 脚本块中的多行以排除 行来自您的输入。

  • 虽然直接使用 Select-String 及其 -NotMatch 开关原则上提供 excluding 匹配行,但您不能有意义地将其与-Context 参数,因为作为上下文捕获的其他行 不受此排除的影响