【问题标题】:Trying to combine replace and new-item in powershell试图在powershell中结合replace和new-item
【发布时间】:2020-08-21 00:26:50
【问题描述】:

我的任务是修改一个目录下的一些Config文件,需要修改的文件有7个,都是以“Monitoring_Tran_xx”开头的。

在这些文件中,某些值(TransactionID="01" AgreedResponseTime="500" SearchProfileID="216") 需要更改,但在所有 7 个文件中都不存在,并且需要在替换或创建它们之前检查它们是否存在。 如果某个参数等于某个值,例如,我也尝试插入一个新参数(使用新项目) if TemplateType = "4152" 然后在它旁边创建一个新参数"DirectoryPoolID = '3' "

感谢您在这方面的帮助。

谢谢

以下配置文件示例:

<?xml *version="1.0"* ?>
<Monitor>
    <Configuration OperatingMode="Transaction" LogFileName="C:\Program Files\*******s\MonitoringOMTR\MonitorLog_01.log" WriteFileInterval="120" ConnectionKey="**********" />
    <TransactionMonitoringConfig TransactionID="01" AgreedResponseTime="500" SearchProfileID="216" />
    <ShowMessages>
        <Message Name="MOISearchStart" />
        <Message Name="MOOSearchFound" />
        <Message Name="MOOSearchEnd" />
        <Message Name="MOOAlert" />
    </ShowMessages>
    <PerformanceCounters TransactionCount="191" TransactionBreaches="0" />
</Monitor>

我尝试过但效果不佳的 Powershell 脚本:

(Get-Content -Path '***FS2072\UserData$\aroyet01\Desktop\HostPS.txt') |
    if ([bool]((Get-Content -Path "***FS2072\UserData$\aroyet01\Desktop\HostPS.txt") -like '*DirectoryPool*', '*SearchProfile*')) { 
write-host "Found it"
}
else {
 write-host "Did not find it"
}
    ForEach-Object {$_ -replace 'TransactionCount="191"', 'TransactionCount="196"'} |
        Set-Content -Path '***FS2072\UserData$\aroyet01\Desktop\HostPS.txt'
Get-Content -Path '***FS2072\UserData$\aroyet01\Desktop\HostPS.txt'

【问题讨论】:

  • 配置文件在
  • 请使用您的配置文件更新您的问题(使用代码格式 - 4 个空格缩进,就像您对脚本所做的那样),而不是将其粘贴为评论。

标签: powershell


【解决方案1】:

我的任务是修改一个目录下的一些Config文件,需要修改的文件有7个,都是以“Monitoring_Tran_xx”开头的。

停止将您的 XML 文件视为原始文本 - 可以以更高的精度解析和处理它们 :)

首先,我们需要将文档解析为 XML,最简单的方法可能是:

$xmlDocument = [xml](Get-Content C:\Path\To\)

由于您有多个具有通用命名模式的文档,我们可能会使用 Get-ChildItem 来发现磁盘上的文件并循环访问它们以获取路径:

Get-ChildItem -Path C:\path\to\config\files\Monitoring_Tran_*.ps1 |ForEach-Object {
  # read each document from disk with `Get-Content`, convert to [xml]
  $xmlDocument = [xml]($_ |Get-Content)
}

接下来,我们需要能够导航我们的 XML 文档。 PowerShell 对此有本机语法绑定:

$tmConfig = $xmlDocument.Monitor.TransactionMonitoringConfig

或者,您也可以使用XPath 表达式来导航文档:

$tmConfig = $xmlDocument.SelectSingleNode("/Monitor/TransactionMonitoringConfig")

在这些文件中,有某些值 (TransactionID="01" AgreedResponseTime="500" SearchProfileID="216") 需要更改,但在所有 7 个文件中都不存在,并且需要在替换或创建它们之前检查它们是否存在

要检查节点上是否存在命名属性,我们可以使用the HasAttribute() method

if($tmConfig.HasAttribute('TransactionID')){
  # attribute exists, let's update it!
  $tmConfig.SetAttribute('TransactionID', 123) # replace 123 with whatever ID you need
}

如果某个参数等于某个值,我也尝试插入一个新参数(使用新项目),例如如果TemplateType = "4152" 然后在它旁边创建一个新参数"DirectoryPoolID = '3' "

如果您只想在另一个属性具有特定值的情况下向节点添加新属性,则可以使用GetAttribute()SetAttribute()

if($xmlNode.GetAttribute('TemplateType') -eq "4152"){
  $xmlNode.SetAttribute("DirectoryPoolID", 3)
}

完成后,将文档保存回文件:

Get-ChildItem -Path C:\path\to\config\files\Monitoring_Tran_*.ps1 |ForEach-Object {
  # read each document from disk with `Get-Content`, convert to [xml]
  $xmlDocument = [xml]($_ |Get-Content)

  <# write all the code to inspect and update the attributes here #>

  # write document back to disk
  $xmlDocument.Save($_.FullName)
}

【讨论】:

  • 嗨,Mathias,感谢您的评论和帮助。
  • 我尝试使用最后一位 - 如前所述,我在中间插入了 if 语句,但返回以下错误:
  • 使用“1”参数调用“SelectSingleNode”的异常:“'\\BBCFS2072\UserData$\aroyet01\Documents\WindowsPowerShell\OMTR\Monitor_Tran*' 具有无效令牌。”在 line:7 char:3 + $tmConfig = $xmlDocument.SelectSingleNode("\\BBCFS2072\UserData$\ar ... + ~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + CategoryInfo : 未指定: (:) [], MethodInvocationException + FullyQualifiedErrorId : DotNetMethodException 您不能在空值表达式上调用方法。在第 18 行 char:4 + if($xmlNode.GetAttribute('TemplateType') -eq "4158"){
  • @TimmyAroyewun 将您的文件系统路径传递给Get-ChildItem,而不是C:\path\to\config\files\Monitoring_Tran_*.ps1。不要更改SelectSingleNode()中的表达式
  • 嗨 Mathias,这就是我得到的,因为我将目录移动到另一个驱动器:使用“1”参数调用“SelectSingleNode”的异常:“'D:\Timmy\OMTR\ Monitor_Transaction_*' 的限定名称无效。”在 line:7 char:3 + $tmConfig = $xmlDocument.SelectSingleNode("D:\Timmy\OMTR\Monitor_Tr ... +
【解决方案2】:

查看您的代码 sn-p i 只能为您提供从基本 Powershell 语法文档开始的建议。

help about_If
help about_Pipelines

给您一个想法...您的if 被放置在管道中。您的 ForEach-Object 未放置在管道中。这两个都不像你发布的那样工作。你可以从这样的开始:

$Content = '***FS2072\UserData$\aroyet01\Desktop\HostPS.txt'
if ($Content -condition 'Yourcondition') {
    $Content | ForEach-Object {
        $_ -replace 'Regex', 'Replacement'
    }
} else {
    'Your else here'
}

要编辑 xml 文件,您可以查看 this post,正如 vonPryz 在 this question today 中所暗示的那样。

【讨论】:

  • 感谢@philmph 的帮助和评论。这项任务有点乏味,如果内容尚不存在,则需要检查并添加新项目。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-04-03
  • 2012-04-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多