Powershell - 将哈希 table 写入带有数组的文件

Powershell - Write Hash table to file with an Array

我想将散列 table 写入一个文件,其中一个数组作为散列 table 项之一。我的数组项写出来了,但它包含 files=System.Object[]

注意 - 一旦成功,我将要反转过程并再次读取哈希 table。

clear-host
$resumeFile="c:\users\paul\resume.log"
$files = Get-ChildItem *.txt
$files.GetType()
write-host
$types="txt"
$in="c:\users\paul"

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:\users\paul\resume.log
files=System.Object[]
types=txt
in=c:\users\paul

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

# 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 ','
    )
  }

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

上面的输出是这样的:

foo=42
bar='baz'
arr='C:\Users\jdoe\file1.txt','C:\Users\jdoe\file2.txt','C:\Users\jdoe\file3.txt'

请参阅底部部分,了解创建 *.psd1 文件的变体,该文件稍后可以使用 Import-PowerShellDataFile.

读回哈希表实例

在文本文件中保存设置/配置数据的备选方案:

  • 如果您不介意承担对第三方模块的依赖:

    • 考虑使用 PSIni module, which uses the Windows initialization file (*.ini) file format; see 作为用法示例。

      • GitHub issue #9035 中提议向 PowerShell 本身添加对初始化文件的支持(从 7.0 开始不存在)。
    • 考虑使用 YAML as the file format; e.g., via the FXPSYaml 模块。

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

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

    • 从 PowerShell 7.0 开始,没有对 编写 的内置支持,例如表示;也就是说,没有互补的 Export-PowerShellDataFile cmdlet。 但是,在 GitHub issue #11300.

      中提议添加此功能
  • 如果创建(大部分)纯文本文件不是 =150=]:

  • 在其支持的数据类型方面提供最大灵活性的解决方案是基于 XML 的 CLIXML 格式Export-Clixml creates, as Lee Dailey suggests, whose output can later be read with Import-Clixml.
    但是,这种格式在 类型保真度 方面也有限制,如 .

    中所述
  • 保存 JSON representation of the data, as Lee also suggests, via ConvertTo-Json / ConvertFrom-Json 是另一种选择,它的输出比 XML 更人性化,但仍然 不是像纯文本表示一样友好;值得注意的是,所有 \ 个字符。在文件路径中必须转义为 \ in JSON.


正在编写一个可以用 Import-PowerShellDataFile

读取的 *.psd1 文件

在规定的数据类型限制内——本质上,任何不是数字或字符串的东西都会变成 字符串——修改代码相当容易top 将 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

如果您稍后用 Import-PowerShellDataFile settings.psd1 阅读 settings.psd1,您将得到一个 [hashtable] 实例,您可以像往常一样访问其条目并产生以下显示输出:

Name                           Value
----                           -----
bar                            baz
arr                            {C:\Users\jdoe\file1.txt, C:\Users\jdoe\file1.txt, C:\Users\jdoe\file1.txt}
foo                            42

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

写入 *.psd1 文件时,您可以通过声明输入哈希表(System.Collections.Hashtable) as [ordered], as shown above (which creates a System.Collections.Specialized.OrderedDictionary 实例)来保留密钥(创建)顺序,但是不幸的是,阅读 *.psd1 文件时订单丢失。

从 PowerShell 7.0 开始,即使您在 @{ *.psd1 文件、[=18= 开头之前放置 [ordered] ] 悄悄地忽略它并创建一个 unordered 哈希表。