PowerShell-使用阵列将哈希表写入文件 [英] Powershell - Write Hash table to file with an Array
问题描述
我想将一个哈希表写到一个文件中,该文件包含一个数组作为哈希表项目之一。我的数组项已写出,但它包含了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-PowerShellDataFile
cmdlet。 但是,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.psd1
和Import-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屋!