问题描述
我有一个文本文件"list.txt",其中包含要解析的数百个URL列表,以及一些通用配置数据,使用"list.txt",就像这样:
I have a text file "list.txt" with a list of hundreds of URL's that I want to parse, along with some common-to-all config data, into individual xml files (config files) using each value in "list.txt", like so:
list.txt包含:
list.txt contains:
line_1
line_2
line_3
样板配置数据如下(以line_1
为例):
The boilerplate config data looks like (using line_1
as an example):
<?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个配置文件分别由和Title
元素编写.
So if "list.txt" contains 100 items, I want 100 config files written with the URL
and Title
elements individualized.
在阅读数组和创建文本文件时,我迷糊了好几篇文章,但是我一直无法使它起作用.
I have fumbled with several posts on reading the array and on creating text files, but I haven't been able to make any of it work.
我尝试过的方法,尽管目前还处于沉思状态.我不确定我从哪里开始或怎么去这里:
What I tried, although it's munged at this point. I'm not sure where I started or how I got to here:
$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技能方式.有人可以帮忙吗?
This is way beyond my neophyte Powershell skills. Can anyone help out?
推荐答案
您正在寻找一种字符串模板化方法,其中引用变量的字符串模板会按需实例化,然后-当前变量值:
You're looking for a string-templating approach, where a string template that references a variable is instantiated on demand with the then-current variable value:
# 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"
,即为每个输入行命名并将其存储在当前位置;根据需要进行调整.
I've chosen UTF-8 encoding for the output XML files, and to name them
"$line.xml"
, i.e. to name them for each input line and to store them in the current location; adjust as needed.
执行模板扩展(插值)操作通过自动变量$ExecutionContext
进行操作,该变量的.InvokeCommand
属性提供对 .ExpandString()
方法的访问,允许执行按需扩展字符串(插入),就像输入字符串是双引号一样-请参见此答案以获得详细示例.
The template expansion (interpolation) is performed 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 this answer for a detailed example.
Ansgar Wiechers 指出,在这种简单情况下,更简单的选择-给定在模板扩展过程中仅传递单个信息-是使用PowerShell的字符串格式运算符-f
填写模板:
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
to fill in the template:
# 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()
之间进行模板扩展:
Optional reading: choosing between -f
and $ExecutionContext.InvokeCommand.ExpandString()
for template expansion:
使用-f
:
-
优点:
Advantages:
-
在调用时明确指出将要填充哪些值.
It is made explicit on invocation what values will be filled in.
-
此外,在占位符中包含格式设置指令也更容易(例如,
{0:N2}
用于格式化带小数点后两位的数字).
Additionally, it's easier to include formatting instructions in placeholders (e.g.,
{0:N2}
to format numbers with 2 decimal places).
显式传递值可以轻松地在不同范围内重用模板.
Passing the values explicitly allows easy reuse of a template in different scopes.
如果您不小心传递了太少或太多的值,默认情况下将发生错误.
An error will occur by default if you accidentally pass too few or too many values.
缺点:
-
-f
占位符始终是位置和抽象;例如,{2}
只是告诉您您正在处理 3rd 占位符,而没有告诉您有关其用途的任何信息;在具有多个占位符的较大模板中,这可能会成为问题.
-f
placeholders are invariably positional and abstract; e.g.,{2}
simply tells you that you're dealing with the 3rd placeholder, but tells you nothing about its purpose; in larger templates with multiple placeholders, this can become an issue.
即使您传递了正确数量的值,它们也可能以错误的顺序排列,这可能会导致细微的错误.
Even if you pass the right number of values, they may be in the wrong order, which can lead to subtle bugs.
使用$ExecutionContext.InvokeCommand.ExpandString()
:
-
优点:
Advantages:
-
如果变量具有描述性名称,则模板将更具可读性,因为占位符(变量名称)将指示其用途.
If your variables have descriptive names, your template will be more readable, because the placeholders - the variable names - will indicate their purpose.
无需在调用时显式传递值-扩展仅依赖于当前作用域中可用的变量.
No need to pass values explicitly on invocation - the expansion simply relies on the variables available in the current scope.
缺点:
-
如果在多个功能(作用域)中使用模板,则需要确保在模板中引用的变量均已设置.
If you use a template in multiple functions (scopes), you need to make sure that the variables referenced in the template are set in each.
至少在默认情况下,$ExecutionContext.InvokeCommand.ExpandString()
会静默忽略模板中引用的不存在的变量-可能需要也可能不需要.
At least by default, $ExecutionContext.InvokeCommand.ExpandString()
will quietly ignore nonexistent variables referenced in the template - which may or may not be desired.
- 但是,您可以使用
Set-StrictMode -Version 2
或更高版本来报告错误;使用Set-StrictMode
通常是一个好习惯,尽管请注意,其效果不是按词法定义的范围,它可以禁用便捷功能.
- However, you can use
Set-StrictMode -Version 2
or higher to report an error instead; usingSet-StrictMode
is good practice in general, though note that its effect isn't lexically scoped and it can disable convenient functionality.
通常,您需要手动将模板与设置模板中引用变量的代码保持同步,以确保将正确的值填充(例如,如果引用变量的名称更改了) ,模板字符串也必须更新).
Generally, you manually need to keep your template in sync with the code that sets the variables referenced in the template, to ensure that the right values will be filled in (e.g., if the name of a referenced variable changes, the template string must be updated too).
这篇关于如何从Powershell中的值数组创建文本文件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!