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

时间:2019-02-27 12:18:41

标签: powershell select-string

我是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"

即使我搜索了Add-Content,我也已经阅读过Powershell Select-StringGet-Content教程。请引导我朝正确的方向,这样我才能实现这一目标。

1 个答案:

答案 0 :(得分:1)

您的方法有两个问题:

  • 正如Mathias R. Jessen在评论中建议的那样,与其将Select-String调用的输出传递到Out-String [1] ,不如访问{{1 }}属性中的结果,其中仅包含匹配的行。

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

我建议完全基于-Raw运算符使用另一种方法,这将使解决方案既简洁又快捷:

-replace
  • (Get-Content $TEST) -replace '^"/AgentSetup/preloadedKs"$', '!$&' | Set-Content $TEST 与每个输入字符串的开头和^的结尾匹配,以便仅匹配除搜索字符串之外仅包含任何内容的行。

  • $是匹配项的占位符,即本例中的原始行;有关$&和这些占位符的更多信息,请参见this answer

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

-replace中包含Get-Content调用可确保从头开始读取文件,从而可以在同一管道中使用(...)写回同一文件;虽然这很方便,但是如果中断写回文件,则可能会导致数据丢失的风险。


[1] Set-Content的目的是创建对象的字符串表示形式,因为它们会打印到控制台上,通常不适合于编程处理;在这种情况下,即使在match-info对象上使用Out-String(或将它们放在.ToString()内)也无法按预期工作,因为结果表示形式也包括输入文件名。