【问题标题】:Powershell Set-Content How to replace multiple linesPowershell Set-Content 如何替换多行
【发布时间】:2017-10-24 11:30:18
【问题描述】:

我有以下 PowerShell 脚本(我使用的是 Powershell v5.1),我主要从上一篇文章中获取和改编:Replace multiline text in a file using Powershell without using Regex:

$oldCode =  @"
        <httpProtocol>
            <customHeaders>
                <clear />
            </customHeaders>
            <redirectHeaders>
                <clear />
            </redirectHeaders>
        </httpProtocol>
"@

$newCode = @"
        <httpProtocol>
            <customHeaders>
                <add name="X-Frame-Options" VALUE="SAMEORIGIN"></add>
            </customHeaders>
            <redirectHeaders>
                <clear />
            </redirectHeaders>
        </httpProtocol>
"@

$Path = "c:\Windows\System32\inetsrv\config\applicationHost.config"
$Content = (Get-Content $Path -Raw).replace($oldCode,$newCode)

Set-Content -Path $Path -Value $Content -Verbose

但是,这不会取代 $oldCode。我使用 Write-Output 来检查 $Content 变量并且它没有替换字符串,所以我假设这是匹配字符串或替换命令本身的问题,而不是 Set-Content 命令的问题.

关于如何让它发挥作用的任何想法?

【问题讨论】:

  • Get-Content,当用于文本文件时,将内容作为字符串数组返回,其中数组中的每个条目是文件的一行。但是,heredoc(这是您用于 $oldcode$newcode 的)是一个简单的字符串,而不是字符串数组,因此 .replace() 失败了。
  • 从我链接的上一篇文章中,我认为-Raw 参数等同于Out-String。如果我添加一个$Content.GetType(),它会告诉我它是一个字符串而不是一个数组(删除-Raw)会将其还原为 System.Array 对象。
  • 我错过了-Raw。链接的帖子使用-replace 运算符,而不是.replace() 方法。两者实际上工作方式不同。其中一个确实使用了正则表达式(但我不记得是哪一个)。尝试将.replace($oldcode,$newcode) 替换为-replace $oldcode,$newcode
  • -replace 使用正则表达式,.Replace() 不使用。话虽如此,您可能希望使用正确的 XML parser 而不是字符串替换。
  • 你说得对,我什至不知道 PowerShell 中的 XML 解析。我已经可以看到它有一些附加和替换点符号。我会看看。谢谢。

标签: xml powershell


【解决方案1】:

所以最后,我使用了以下内容。这不是您也可以使用 API 来构造元素的唯一选择。

$xmlPath = "c:\windows\system32\inetsrv\config\applicationHost.config"

[xml]$xml = Get-Content -Path $xmlPath

[xml]$xFrameXml = @"
            <customHeaders>
                <add name="X-Frame-Options" value="SAMEORIGIN" />
            </customHeaders>
"@

foreach($node in $xml.SelectNodes('/configuration/system.webServer/httpProtocol/customHeaders')){
    $node.ParentNode.AppendChild($xml.ImportNode($xFrameXml.customHeaders, $true));
    $node.ParentNode.RemoveChild($node);

}
$xml.Save($xmlPath);

您也可以使用.ReplaceChild,但我还没有找到正确的语法,所以如果有人这样做,它可能会更干净。

感谢 Ansgar 为我指明了正确的方向。

【讨论】:

  • @"One line/Twolines"@ 解决方案称为 here-string,这是一种很好的处理方式,但请记住它不适用于 PowerShell 2。如果您正在寻找编写完全兼容的代码,这种方法不兼容唉。
猜你喜欢
  • 1970-01-01
  • 2014-08-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-10-06
  • 2018-05-10
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多