在Powershell中更新变量的txt文件

时间:2018-07-19 14:25:19

标签: powershell

所以我今天的挑战。

我有一个配置文件(实际上只是一个txt文档),该文件存储变量以存储脚本之间传递的信息或在重启后使用的信息。

我正在寻找一种更有效的方式来读取和更新文件。目前,我通过以下方式读取文件:

Get-Content $current\Install.cfg | ForEach-Object {
    Set-Variable -Name line -Value $_
    $a, $b = $line.Split('=')
    Set-Variable -name $a -Value $b
}

但是要覆盖内容,我使用以下命令重新创建文件:

ECHO OSV=$OSV     >>"$ConfigLoc\tool.cfg"
ECHO OSb=$OSb     >>"$ConfigLoc\tool.cfg"
ECHO cNum=$cNum   >>"$ConfigLoc\tool.cfg"
ECHO cCode=$cCode >>"$ConfigLoc\tool.cfg"
ECHO Comp=$Comp   >>"$ConfigLoc\tool.cfg"

每次添加新的已保存变量时,我都将新变量硬编码到原始配置文件和配置更新程序中。 由于我的下一个更新要求将当前的15个变量增加到当前的15个变量。

Get-Content $current\Install.cfg | ForEach-Object {
    Set-Variable -Name line -Value $_
    $a, $b = $line.Split('=')
    ECHO $a=$$a
}

$$a在循环中使用变量$ a作为变量名称来加载值。 我可以说明的最佳例子是:

   ECHO $a=$$a    (in current loop)
   Echo OSV=$OSV  (actually appears in code as)

不确定如何再次阐明这一点,或者不确定如何在变量标题也是变量的情况下实现它。

3 个答案:

答案 0 :(得分:0)

如果您要创建一个具有name = value参数的文件,这是另一种建议。这是我每天使用的真实脚本的片段。您可以对其进行修改,以便它读取您的.csv输入并使用它代替硬编码值。

$Sites = ("RawSiteName|RoleName|DevUrl|SiteID|HttpPort|HttpsPort", `
    "SiteName|Name of role|foo.com|1|80|443" `    
     ) | ConvertFrom-CSV -Delimiter "|"

   $site = $sites[0]
   Write-Host "RawSiteName =$($site.RawSiteName)"

您也许可以使用类似于$text = Get-Content MyParameters.csv的东西并将其通过管道传递到ConvertFrom-CSV cmdlet。我意识到这并不是您正在做的事情的直接答案,但是它可以让您以编程方式创建一个跨脚本传递的文件。

答案 1 :(得分:0)

从本质上讲,您正在寻找可变间接:通过存储在另一个变量中的名称间接访问变量

在PowerShell中, Get-Variable 允许您执行此操作,如下所示:

# Sample variables.
$foo='fooVal'
$bar='barVal'

# List of variables to append to the config file -
# the *names* of the variables above.
$varsToAdd = 
  'foo',
  'bar'

# Loop over the variable names and use string expansion to create <name>=<value> lines.
# Note how Get-Variable is used to retrieve each variable's value via its *name*.
$(foreach ($varName in $varsToAdd) {
  "$varName=$(Get-Variable $varName -ValueOnly)"
}) >> "$ConfigLoc/tool.cfg"

通过上述操作,以下几行会附加到输出*.cfg文件中:

foo=fooVal
bar=barVal

请注意,您ConvertFrom-StringData可以更轻松地读取这样的文件,该文件会输出一个 hashtable ,其中包含来自文件

$htSettings = Get-Content -Raw "$ConfigLoc/tool.cfg" | ConvertFrom-StringData

例如,访问$htSettings.foo将返回fooVal


使用哈希表 作为设置容器, 更新配置文件变得更加容易,因为您可以简单地使用所有设置及其当前值重新创建文件

$htSettings.GetEnumerator() |
  ForEach-Object { "$($_.Key)=$($_.Value)" } > "$ConfigLoc/tool.cfg"

注意:默认情况下,PowerShell不会枚举管道中哈希表的条目,这就是为什么需要.GetEnumerator()的原因。


不过,通常,这种手动序列化很麻烦,正如其他人所指出的那样,并且还有很多健壮的(虽然通常不那么友好)替代方案。

使用基于字符串和行的序列化方法,需要注意两件事:

  • 所有值都保存为字符串,因此,如果不是所有对象都提供有意义的字符串表示形式,则在必要时,甚至有可能必须手动将其转换为所需的数据类型。

    • 通常,最健壮的序列化格式是Export-CliXml,但请注意,它不是 friendly 格式-请谨慎进行手动编辑。
  • ConvertFrom-StringData失败,并且配置文件中的名称重复,这意味着您必须手动确保在添加到文件时不创建重复的条目-如果您每次都使用上述方法从哈希表重新创建文件,但是,这是安全的。

答案 2 :(得分:0)

感谢大家的帮助。这是我要解决的问题。导入和导出再简单不过了。如果我必须手动更新XML安装默认值,那么我可以轻松实现,这也很棒。我也喜欢这样一个事实,即使您以$Test的身份导入,仍然可以使用$original来访问变量。我将创建多个哈希表来组织今后将要使用的不同数据,并仅将其导入/导出为$config变量作为主变量。

$original = @{
    OSV='0'
    OSb='0'
    cNum='00000'
    cCode='0000'
    Client='Unknown'
    Comp='Unknown'
}

$original | Export-Clixml $Home\Desktop\sample.cfg

$Test = Import-Clixml $Home\Desktop\sample.cfg

Write $Test
Write $original.Client