我有一个文本文件“list.txt”,其中包含要解析的数百个URL列表,以及一些通用配置数据,使用“list.txt”中的每个值解析为单个xml文件(配置文件) ”,就像这样:

list.txt包含:

line_1
line_2
line_3

样板配置数据如下所示(以line_1为例):
<?xml version="1.0"?>
<Website xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <Url>line_1.mydomain.com</Url>
  <Title>line_1</Title>
  <Enabled>true</Enabled>
  <PluginInName>Tumblr</PluginInName>
</Website>

因此,如果“list.txt”包含100个项目,我希望100个配置文件分别与URLTitle元素一起编写。

在阅读数组和创建文本文件时,我迷糊了几篇文章,但是我无法使其工作。

我尝试过的方法,尽管目前还不成熟。我不确定我从哪里开始或如何到达这里:
$FileName = "C:\temp\list.txt"
$FileOriginal = Get-Content $FileName

# create an empty array
Foreach ($Line in $FileOriginal)
{
    $FileModified += $Line

    if ($Line -match $pattern)
    {
        # Add Lines after the selected pattern
        $FileModified += 'add text'
        $FileModified += 'add second line text'
    }
}
Set-Content $fileName $FileModified

这是超越我新手Powershell技能的。有人可以帮忙吗?

最佳答案

您正在寻找一种字符串模板化方法,其中使用当时最新的变量值按需实例化引用变量的字符串模板:

# Define the XML file content as a *template* string literal
# with - unexpanded - references to variable ${line}
# (The {...}, though not strictly necessary here,
# clearly delineates the variable name.)
$template = @'
<code>
<?xml version="1.0"?>
<Website xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <Url>${line}.mydomain.com</Url>
  <Title>${line}</Title>
  <Enabled>true</Enabled>
  <PluginInName>Tumblr</PluginInName>
</Website>
'@


# Loop over all input lines.
Get-Content C:\temp\list.txt | ForEach-Object {
   $line = $_ # store the line at hand in $line.
   # Expand the template based on the current $line value.
   $configFileContent = $ExecutionContext.InvokeCommand.ExpandString($template)
   # Save the expanded template to an XML file.
   $configFileContent | Set-Content -Encoding Utf8 "$line.xml"
}
笔记:
  • 我为输出XML文件选择了UTF-8编码,并将其命名为"$line.xml",即为每个输入行命名它们并将它们存储在当前位置;根据需要进行调整。
  • 模板扩展(插值)是通过执行via automatic variable $ExecutionContext 来完成的,该模板的.InvokeCommand属性提供对 .ExpandString() 方法的访问,该允许按需执行字符串扩展(插值),就像输入字符串是双引号字符串一样-请参见this answer有关详细示例。
  • 通过$ExecutionContext.InvokeCommand.ExpandString() cmdlet以更容易发现的方式显示Expand-String方法的功能是this GitHub feature request的主题。


  • Ansgar Wiechers指出,在这种简单情况下,考虑到模板扩展过程中仅传递一条信息,在这种简单情况下,可以使用更简单的替代来替代,请使用PowerShell的string-formatting operator, -f 来填充模板:
    # Define the XML file content as a *template* string literal
    # with '{0}' as the placeholder for the line variable, to
    # be instantiated via -f later.
    $template = @'
    <code>
    <?xml version="1.0"?>
    <Website xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:xsd="http://www.w3.org/2001/XMLSchema">
      <Url>{0}.mydomain.com</Url>
      <Title>{0}</Title>
      <Enabled>true</Enabled>
      <PluginInName>Tumblr</PluginInName>
    </Website>
    '@
    
    
    # Loop over all input lines.
    Get-Content C:\temp\list.txt | ForEach-Object {
       # Expand the template based on the current $line value.
       $configFileContent = $template -f $_
       # Save the expanded template to an XML file.
       $configFileContent | Set-Content -Encoding Utf8 "$line.xml"
    }
    

    可选阅读:在-f$ExecutionContext.InvokeCommand.ExpandString()之间进行选择以进行模板扩展:
    向安斯加尔求助。
    使用-f:
  • 优点:
  • 在调用时明确指出将要填充哪些值。
  • 此外,在占位符中包含格式设置指令也更容易(例如,使用{0:N2}格式化带两位小数位的数字)。
  • 显式传递值可以轻松地在不同范围内重用模板。

  • 如果您不小心传递了太少或太多的值,默认情况下将发生错误。

  • 的缺点:
  • -f占位符总是位置和抽象的。例如,{2}只是告诉您您正在使用第3个占位符,而没有告诉您有关其目的的任何信息;在具有多个占位符的较大模板中,这可能会成为一个问题。
  • 即使您传递正确数量的值,它们的顺序也可能不正确,这可能会导致细微的错误。


  • 使用$ExecutionContext.InvokeCommand.ExpandString():
  • 优点:
  • 如果变量具有描述性名称,则模板将更具可读性,因为占位符(变量名称)将指示其用途。
  • 无需在调用时显式传递值-扩展仅依赖于当前作用域中可用的变量。

  • 的缺点:
  • 如果您在多个功能(范围)中使用模板,则需要确保在每个模板中都设置了模板中引用的变量。
  • 至少默认情况下,$ExecutionContext.InvokeCommand.ExpandString()将安静地忽略模板中引用的不存在的变量-可能需要也可能不需要。
  • 但是,您可以使用Set-StrictMode -Version 2或更高版本来报告错误。通常,使用Set-StrictMode是一个好习惯,不过请注意,它的作用是isn't lexically scoped,并且可以disable convenient functionality
  • 通常,您需要手动将模板与设置模板中引用变量的代码保持同步,以确保将正确的值填充(例如,如果引用变量的名称发生更改,则模板字符串必须也将被更新)。

  • 07-24 09:38
    查看更多