【问题标题】:PowerShell - Replace the third and fourth occurrence of a stringPowerShell - 替换字符串的第三次和第四次出现
【发布时间】:2020-04-20 09:57:23
【问题描述】:

我有一个 xml 文件,我想替换第三次和第四次出现的字符串。我已经尝试了很多东西,但无法让它工作(甚至关闭,所以我认为这里没有任何意义)。下面我有一个具有类似结构的示例 XML。我想要的是替换第三次和第四次出现的 book 以使其不同(例如 book2)。

<?xml version="1.0"?>
<catalog>
   <book>
      <author>Gambardella, Matthew</author>
      <title>XML Developer's Guide</title>
      <genre>Computer</genre>
      <price>44.95</price>
      <publish_date>2000-10-01</publish_date>
      <description>An in-depth look at creating applications 
      with XML.</description>
   </book>
   <book>
      <author>Ralls, Kim</author>
      <title>Midnight Rain</title>
      <genre>Fantasy</genre>
      <price>5.95</price>
      <publish_date>2000-12-16</publish_date>
      <description>A former architect battles corporate zombies, 
      an evil sorceress, and her own childhood to become queen 
      of the world.</description>
   </book>
</catalog>

我想要的是替换“book”的第三和第四次出现,使其与“book2”不同。

我希望文件在代码运行时具有以下内容。

<?xml version="1.0"?>
<catalog>
   <book>
      <author>Gambardella, Matthew</author>
      <title>XML Developer's Guide</title>
      <genre>Computer</genre>
      <price>44.95</price>
      <publish_date>2000-10-01</publish_date>
      <description>An in-depth look at creating applications 
      with XML.</description>
   </book>
   <book2>
      <author>Ralls, Kim</author>
      <title>Midnight Rain</title>
      <genre>Fantasy</genre>
      <price>5.95</price>
      <publish_date>2000-12-16</publish_date>
      <description>A former architect battles corporate zombies, 
      an evil sorceress, and her own childhood to become queen 
      of the world.</description>
   </book2>
</catalog>

然后我将运行下面的代码。

$filePathToTask = "C:\Users\Dan\Desktop\Books.xml"
$xml = New-Object XML
$xml.Load($filePathToTask)
$element =  $xml.SelectSingleNode("/catalog/book2/genre")
$element.InnerText = "Fiction"
$xml.Save($filePathToTask)

最后我会将代码恢复为“Book”

最终输出如下。

<?xml version="1.0"?>
<catalog>
   <book>
      <author>Gambardella, Matthew</author>
      <title>XML Developer's Guide</title>
      <genre>Computer</genre>
      <price>44.95</price>
      <publish_date>2000-10-01</publish_date>
      <description>An in-depth look at creating applications 
      with XML.</description>
   </book>
   <book>
      <author>Ralls, Kim</author>
      <title>Midnight Rain</title>
      <genre>Fiction</genre>
      <price>5.95</price>
      <publish_date>2000-12-16</publish_date>
      <description>A former architect battles corporate zombies, 
      an evil sorceress, and her own childhood to become queen 
      of the world.</description>
   </book>
</catalog>

我对 PowerShell 很陌生,所以我很感激任何帮助。

丹尼尔

【问题讨论】:

  • 我认为您不应该这样做,因为这会使应用程序更难过滤出书籍数组。如果必须,我建议为每个 &lt;book&gt; 元素添加一个属性。像&lt;book index="1"&gt;&lt;book index="2"&gt; 等。
  • 我同意Theo 的观点,即您所说的会破坏 XML 文件的含义。将您的第一个 XML 加载到 $Test0,您可以看到单独的书籍 $Test0.catalog.book[0]。您可以优雅地遍历集合。在 $Test2 中使用您的第二个 XML 是不允许的,因为每个 book# 将显示为不同的 property 而不是不同的集合项。
  • 感谢您的回复。我这样做的原因是因为代码是由第三方开发的,并且有一个已知的错误,该错误在下游有一个解决方法。所以我想要做的是将“book”的第三和第四次出现更改为“book2”,然后使用$element = SelectSingleNode("/catalog/book2/genre") $element.InnerText = "Fiction"替换流派的内部,然后将“book2”更改回“book”以返回代码正常。
  • @Daniel - 如果文件很短,那么我会遍历它,计算&lt;book&gt; 行,并在找到时更改第 3 和第 4 行。
  • @Lee_Dailey 该文件非常短,只有 55 行,永远不会变大。您的建议我相信会起作用,但是代码的结构如何?你能举个例子吗?

标签: powershell


【解决方案1】:

我猜你想要类似的东西:

$filePathToTask = "C:\Users\Dan\Desktop\Books.xml"
$xml = New-Object XML
$xml.Load($filePathToTask)
$root = $xml.DocumentElement

$books = $root.SelectNodes("/catalog/book")

# Modify the 2nd book genre
$books[1].genre = "Fiction"

$xml.Save($filePathToTask)

无需创建中间 XML。

【讨论】:

    【解决方案2】:

    假设只有两个 &lt;book&gt;&lt;/book&gt; 块,这似乎是你想要的...... [grin] 我仍然无法理解它的原因,但这不是重要的。

    代码的作用...

    • 将文件读取为文本行数组
      当您准备好使用真实数据时,注释掉整个#region/#endregion 块并用Get-Content 调用替换它。
    • 设置目标和替换字符串
    • 将“找到的目标”计数设置为零
    • 遍历行数组
    • 统计目标字符串
    • 一旦$TCount 超过2,它就会用替换字符串替换目标
    • 将当前的$Line 发送到$UpdatedInStuff 集合
    • 在屏幕上显示

    这是代码...

    #region >>> fake reading in a file
    #    in real life, use Get-Content
    $InStuff = @'
    <?xml version="1.0"?>
    <catalog>
       <book>
          <author>Gambardella, Matthew</author>
          <title>XML Developer's Guide</title>
          <genre>Computer</genre>
          <price>44.95</price>
          <publish_date>2000-10-01</publish_date>
          <description>An in-depth look at creating applications 
          with XML.</description>
       </book>
       <book>
          <author>Ralls, Kim</author>
          <title>Midnight Rain</title>
          <genre>Fantasy</genre>
          <price>5.95</price>
          <publish_date>2000-12-16</publish_date>
          <description>A former architect battles corporate zombies, 
          an evil sorceress, and her own childhood to become queen 
          of the world.</description>
       </book>
    </catalog>
    '@ -split [System.Environment]::NewLine
    #endregion >>> fake reading in a file
    
    $Target = 'book>'
    $TReplace = 'book2>'
    
    $TCount = 0
    $UpdatedInStuff = foreach ($Line in $InStuff)
        {
        if ($Line -match $Target)
            {
            $TCount ++
            }
        if ($TCount -gt 2)
            {
            $Line = $Line -replace $Target, $TReplace
            }
    
        $Line
        }
    
    $UpdatedInStuff
    

    输出...

    <?xml version="1.0"?>
    <catalog>
       <book>
          <author>Gambardella, Matthew</author>
          <title>XML Developer's Guide</title>
          <genre>Computer</genre>
          <price>44.95</price>
          <publish_date>2000-10-01</publish_date>
          <description>An in-depth look at creating applications 
          with XML.</description>
       </book>
       <book2>
          <author>Ralls, Kim</author>
          <title>Midnight Rain</title>
          <genre>Fantasy</genre>
          <price>5.95</price>
          <publish_date>2000-12-16</publish_date>
          <description>A former architect battles corporate zombies, 
          an evil sorceress, and her own childhood to become queen 
          of the world.</description>
       </book2>
    </catalog>
    

    【讨论】:

      猜你喜欢
      • 2016-11-02
      • 2016-04-09
      • 1970-01-01
      • 2011-08-25
      • 2018-08-11
      • 1970-01-01
      • 2022-10-07
      相关资源
      最近更新 更多