根据内容有选择地更新文件中的行

Selectively update lines in a file based on their content

我是 Powershell 脚本的新手,我已经完成了 Powershell 教程以完成我当前的脚本要求。

我正在尝试通过匹配模式向该行添加感叹号。我有类似的 test.default 文件如下

"/AgentSetup/__type__"

"/AgentSetup/__name__"

"/AgentSetup/preloadedKs"

"/AgentSetup/preloadedKMsArch"

"/AgentSetup/loadOnlyPreloadedKMs"

文件中有更多这样的行

所以在这里我尝试通过匹配将感叹号添加到行的开头,例如如果我搜索“/AgentSetup/preloadedKs”= {REPLACE=""},那么在文件中它应该看起来像

"/AgentSetup/__type__"

"/AgentSetup/__name__"

"/AgentSetup/preloadedKs"

!"/AgentSetup/defaultAccount"

"/AgentSetup/preloadedKMsArch"

"/AgentSetup/loadOnlyPreloadedKMs"

我尝试了以下命令来实现这个但没有成功

$TEST = "C:\Asset\config.default"
$Pattern = "/AgentSetup/defaultAccount"
$var = "!" + (Select-String -Path $TEST -pattern $Pattern | Out-String)
$var
$var + (Get-Content $TEST -Raw) | Set-Content $TEST

以上命令不仅仅是添加感叹号,而是在文件中添加重复条目,如下所示:

!

test.default:103:"/AgentSetup/defaultAccount"

我已经完成了 powershell Add-ContentSelect-String 教程,甚至我搜索了 Get-Content。请引导我朝着正确的方向前进,这样我才能做到这一点,这会有所帮助。

你的方法有两个问题:

  • 作为 Mathias R. Jessen suggests in a comment, instead of piping the Select-String 调用的输出到 Out-String[1],访问 .Line 属性结果,仅包含匹配的行。

  • 您只是将感兴趣的行的修改副本添加到您的输出中,这意味着 原始的、未修改的行仍然是重写文件的一部分.

我建议使用完全不同的方法,基于 -replace 运算符,这使得解决方案更简洁、更快速:

(Get-Content $TEST) -replace '^"/AgentSetup/preloadedKs"$', '!$&' | Set-Content $TEST
  • ^ 匹配每个输入字符串的开头和 $ 结尾,因此只匹配只包含搜索字符串的行。

  • $& 是匹配内容的占位符,即本例中的原始行;有关 -replace 和这些占位符的更多信息,请参阅 .

请注意,这会将行更新到其原始位置。

(...) 中包含 Get-Content 调用可确保预先完整读取文件,从而可以在同一管道中使用 Set-Content 写回同一文件;虽然这很方便,但如果回写文件被中断,它会带来轻微的数据丢失风险。


[1] Out-String 的目的是创建对象的字符串表示 因为它们会打印到控制台 ,这通常不是适用于程序化处理;即使在匹配信息对象上使用 .ToString()(或将它们放在 "..." 中)在这种情况下也不会按预期工作,因为生成的表示也包含输入文件名。