PowerShell-使用阵列将哈希表写入文件 [英] Powershell - Write Hash table to file with an Array

查看:18
本文介绍了PowerShell-使用阵列将哈希表写入文件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想将一个哈希表写到一个文件中,该文件包含一个数组作为哈希表项目之一。我的数组项已写出,但它包含了FILES=System.Object[]

注意-一旦此方法起作用,我将希望反转该过程并再次读回哈希表。

clear-host
$resumeFile="c:userspaul
esume.log"
$files = Get-ChildItem *.txt
$files.GetType()
write-host
$types="txt"
$in="c:userspaul"

Remove-Item $resumeFile -ErrorAction SilentlyContinue
$resumeParms=@{}
$resumeParms['types']=$types
$resumeParms['in']=($in)
$resumeParms['files']=($files)
$resumeParms.GetEnumerator() | ForEach-Object {"{0}={1}" -f $_.Name,$_.Value} | Set-Content $resumeFile
write-host "Contents of $resumefile"
get-content $resumeFile

结果

IsPublic IsSerial Name                                     BaseType                                                      
-------- -------- ----                                     --------                                                      
True     True     Object[]                                 System.Array                                                  

Contents of c:userspaul
esume.log
files=System.Object[]
types=txt
in=c:userspaul

推荐答案

直接的解决办法是创建您自己的数组表示,方法是枚举元素并用,分隔它们,'...'中括起字符串值:

# Sample input hashtable. [ordered] preserves the entry order.
$resumeParms = [ordered] @{ foo = 42; bar = 'baz'; arr = (Get-ChildItem *.txt) }

$resumeParms.GetEnumerator() |
  ForEach-Object { 
    "{0}={1}" -f $_.Name, (
      $_.Value.ForEach({ 
       (("'{0}'" -f ($_ -replace "'", "''")), $_)[$_.GetType().IsPrimitive] 
      }) -join ','
    )
  }

这并不是说它通过.ToString()表示将所有非基元.NET类型表示为字符串,这可能不够好,也可能不够好。

上面的输出类似于:

foo=42
bar='baz'
arr='C:Usersjdoefile1.txt','C:Usersjdoefile2.txt','C:Usersjdoefile3.txt'

有关创建*.psd1文件的变体,请参阅底部部分,该文件稍后可使用Import-PowerShellDataFile读回到哈希表实例中。


在文本文件中保存设置/配置数据的替代方法:

  • 如果您不介意依赖第三方模块

    • 考虑使用PSIni模块,该模块使用Windows初始化文件(*.ini)文件格式;有关用法示例,请参阅this answer

      • 建议在GitHub issue #9035中向PowerShell本身添加对初始化文件的支持(从7.0开始不存在)。
    • 考虑使用YAML作为文件格式;例如,通过FXPSYaml模块。

      • GitHub issue #3607中建议将对YAML文件的支持添加到PowerShell本身(从7.0开始不存在)。
  • Configuration模块提供对*.psd1文件进行写入和读取的命令,这些命令基于持久化的PowerShell哈希表文字,正如您在源代码中声明的那样。

    • 或者,您可以修改顶部代码中的输出格式,以自己生成此类文件,从而允许您通过
      回读它们 Import-PowerShellDataFile,如下部所示。

    • 从PowerShell 7.0开始,没有对编写(如表示)的内置支持;也就是说,没有补充的Export-PowerShellDataFilecmdlet。 但是,GitHub issue #11300中建议添加此功能。

  • 如果创建(主要)纯文本文件不是必须

  • 在其支持的数据类型方面提供最大灵活性的解决方案是Export-Clixml创建的基于XML的CLIXML格式,其输出可在以后使用Import-Clixml读取。
    但是,此格式在类型保真度方面也有限制,如this answer中所述。

  • 保存数据的JSON是另一种选择,通过ConvertTo-Json/ConvertFrom-Json保存数据的表示形式,这将使输出比XML更友好,但仍不如纯文本表示形式友好;值得注意的是,所有字符。文件中的路径必须在JSON中转义为\


编写可使用Import-PowerShellDataFile读取的*.psd1文件

在所述的有关数据类型的约束中-本质上,任何不是数字或字符串的都会变成字符串-修改顶部的代码以将PowerShell哈希表文字表示写入*.psd1文件,以便可以作为[hashtable]实例通过Import-PowerShellDataFile

回读

如上所述,如果您不介意安装模块,请考虑Configuration模块,它内置了此功能。

# Sample input hashtable.
$resumeParms = [ordered] @{ foo = 42; bar = 'baz'; arr = (Get-ChildItem *.txt) }

# Create a hashtable-literal representation and save it to file settings.psd1
@"
@{
$(
  ($resumeParms.GetEnumerator() |
    ForEach-Object { 
      "  {0}={1}" -f $_.Name, (
        $_.Value.ForEach({ 
          (("'{0}'" -f ($_ -replace "'", "''")), $_)[$_.GetType().IsPrimitive] 
         }) -join ','
      )
    }
  ) -join "`n"
)
}
"@ > settings.psd1

如果您稍后阅读settings.psd1Import-PowerShellDataFile settings.psd1,您将获得一个[hashtable]实例,您可以照常访问其条目,并生成以下显示输出:

Name                           Value
----                           -----
bar                            baz
arr                            {C:Usersjdoefile1.txt, C:Usersjdoefile1.txt, C:Usersjdoefile1.txt}
foo                            42

请注意保留条目(键)的顺序,因为哈希表条目本身是无序的。

写入*.psd1文件时,您可以通过将输入哈希表(System.Collections.Hashtable)声明为[ordered]来保留键(-创建)顺序,如上所示(这将创建一个System.Collections.Specialized.OrderedDictionary实例),但不幸的是,读取*.psd1文件时丢失了顺序。

从PowerShell 7.0开始,即使您在*.psd1文件中将[ordered] 放在@{之前,Import-PowerShellDataFile也会忽略它并创建一个无序哈希表。

这篇关于PowerShell-使用阵列将哈希表写入文件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆