如何从 Powershell 中的值数组创建文本文件

How to Create Text Files from an Array of Values in Powershell

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

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 个项目,我想要使用 URLTitle 元素个性化编写的 100 个配置文件。

我在几篇关于读取数组和创建文本文件的帖子中摸索过,但我无法使它们发挥作用。

我尝试过的方法,尽管此时已经过时了。我不确定我从哪里开始或如何到达这里:

$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, whose .InvokeCommand property provides access to the .ExpandString() method, which allows performing string expansion (interpolation) on demand, as if the input string were a double-quoted string - see 详细示例

    • 通过 Expand-String cmdlet 以更易于发现的方式展示 $ExecutionContext.InvokeCommand.ExpandString() 方法 的功能是this GitHub feature request.
    • 的主题

Ansgar Wiechers points out that a simpler alternative in this simple case - given that only a single piece of information is passed during template expansion - is to use PowerShell's 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()进行模板扩展:

感谢 Ansgar 的帮助。

使用-f:

  • 优点:

    • 在调用时明确说明将填充哪些值。

      • 此外,在占位符中包含格式化指令会更容易(例如,{0:N2} 将数字格式化为小数点后两位)。

      • 显式传递值允许在不同范围内轻松重用模板。

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

  • 缺点:

  • -f 占位符总是位置和抽象;例如,{2} 只是告诉你你正在处理 3rd 占位符,但没有告诉你它的用途;在具有多个占位符的较大模板中,这可能会成为一个问题。

    • 即使您传递了正确数量的值,它们的顺序也可能是错误的,这会导致细微的错误。

使用$ExecutionContext.InvokeCommand.ExpandString()

  • 优点:

    • 如果您的变量具有描述性名称,您的模板将更具可读性,因为占位符 - 变量名称 - 将表明它们的用途。

    • 无需在调用时显式传递值 - 扩展仅依赖于当前作用域中可用的变量。

  • 缺点:

  • 如果你在多个函数(作用域)中使用一个模板,你需要确保在每个函数(作用域)中都设置了模板中引用的变量。

  • 至少在默认情况下,$ExecutionContext.InvokeCommand.ExpandString() 会安静地忽略模板中引用的不存在的变量——这可能是需要的,也可能不需要。

    • 不过,您可以使用Set-StrictMode -Version 2或更高版本来报错;使用 Set-StrictMode 通常是很好的做法,但请注意它的效果 isn't lexically scoped and it can disable convenient functionality.

    • 通常,您需要手动使模板与设置模板中引用的变量的代码保持同步,以确保填写正确的值(例如,如果名称引用的变量发生变化,模板字符串也必须更新。