我试图避免使用powershell中常用的极其冗长的哈希Map和数组。为什么?因为我有100行,而且当我只需要一个CSV类型的数组时,必须将每一行都 Package 在@(name='foo; id='bar')
等中是没有任何意义的。
$header = @('name', 'id', 'type', 'loc')
$mycsv = @(
# name, id, type, loc
'Brave', 'Brave.Brave', 1, 'winget'
'Adobe Acrobat (64-bit)', '{AC76BA86-1033-1033-7760-BC15014EA700}', 2, ''
'GitHub CLI', 'GitHub.cli', 3, 'C:\portable'
)
# Do some magic here to set the CSV / hash headers so I can use them as shown below
Foreach ($app in $mycsv) {
Write-Host "App Name: $app.name"
Write-Host "App Type: $app.type"
Write-Host "App id : $app.id"
Write-Host "App Loc : $app.type"
Write-Host ("-"*40)
}
我相信你明白我的意思。
那么,如何使用标头名称逐行处理内联CSV?
预期输出:
App Name: Brave
App Type: 1
App id : Brave.Brave
App Loc : winget
----------------------------------------
...
更新:2022-12-03
最终的解决方案是以下非常简短的代码:
$my = @'
name,id,type,loc
Brave, Brave.Brave,1,winget
"Adobe Acrobat (64-bit)",{AC76BA86-1033-1033-7760-BC15014EA700},2,
GitHub CLI,GitHub.cli,,C:\portable
'@
ConvertFrom-Csv $my | % {
Write-Host "App Name: $($_.name)"
Write-Host "App Type: $($_.type)"
Write-Host "App id : $($_.id)"
Write-Host "App Loc : $($_.loc)"
Write-Host $("-"*40)
}
💖 👍
3条答案
按热度按时间ztyzrc3y1#
您可以使用内存中,即CSV数据的字符串表示形式(使用here-string),并使用
ConvertFrom-Csv
将其解析为 * 对象*:$mycsv | Format-List
然后提供所需的输出(如果没有Format-List
,您将得到隐式的Format-Table
,因为对象的属性不超过4个)。Format-List
* 本质上 * 提供了您在Write-Host
调用循环中尝试过的for-display格式;如果您确实需要后一种方法,请注意,正如Walter Mitty's answer中所指出的,您需要将属性访问 * 表达式 *(如$_.name
)括在$(...)
中,以便在可扩展(双引号)PowerShell字符串("..."
)中进行扩展-有关PowerShell可扩展字符串(字符串插值)语法的系统概述,请参见this answer。注意事项:
,
本身时。,
的字段值周围使用**"..."
(* 双 *-引号)**('...'
,即 * 单 *-引号在CSV数据中 * 不 * 具有语法意义,并且任何'
字符 * 逐字 * 保留)。"
字符,则将其转义为""
,
以外的分隔符 *(例如|
),并通过**-Delimiter
**参数将其传递给ConvertFrom-Csv
。ConvertFrom-Csv
(以及Import-Csv
)创建的对象的属性都是 * string *([string
]-typed)。可选阅读:一种自定义CSV表示法,允许创建 typed 属性:
便利函数**
ConvertFrom-CsvTyped
(下面的源代码)通过启用*自定义标头表示法 (支持在标头行中的每个列名前面加上 type literal),克服了ConvertFrom-Csv
总是只创建 string 类型属性的限制;例如[int] ID
(有关PowerShell类型文字的系统概述,请参见this answer,它可以引用任何.NET类型)。这使您能够从输入CSV创建(非字符串) 类型化 * 属性**,只要目标类型的值可以表示为数字或字符串文字,其中包括:
[int]
、[long]
、[double]
、[decimal]
...)[datetime]
、[datetimeoffset]
和[timespan]
[bool]
(使用0
和1
作为列值)[timespan] '01:00'
或[byte] 0x40
范例-请注意第二个和第三个数据行名称
[int]
和[datetime]
之前的型别常值:输出-注意十六进制数是如何被识别的(默认情况下是十进制格式),以及数据字符串是如何被识别为
[datetime]
示例的:通过将**
-AsSourceCode
添加到上述调用,可以将解析的对象 * 输出为PowerShell源代码 * 字符串**,即输出为**[pscustomobject]
文字数组**:Output -请注意,如果您在脚本中使用它或将其作为
Invoke-Expression
的输入(仅用于测试),您将获得与上面相同的对象和for-display输出:ConvertFrom-CsvTyped
源代码:hrirmatl2#
这里有一些技巧可以帮助你使用CSV格式的数据。我对你的输入做了一些修改。我没有定义一个单独的标题,而是将标题记录作为CSV数据的第一行。这正是ConvertFrom-CSV所期望的。我还将单引号改为双引号。我完全省略了一个字段。
第一个输出显示了如果将ConvertFrom-CSV的输出提供给format-List会发生什么。如果您的计划是在变量中使用数据,我不建议您这样做。format-list适合显示,但不适合进一步处理。
第二个输出模拟了示例输出。here字符串包含各种子表达式,每个子表达式都可以通过自动变量$_访问当前数据。
最后,我将向您展示管道流的成员。请注意,四个属性的名称来自您的字段名。
lmvvr0a83#
若要在PowerShell指令码中行程内嵌CSV,您可以使用ConvertFrom-Csv Cmdlet将CSV数据转换成具有可在指令码中使用之属性的对象。以下是如何使用此Cmdlet行程指令码中CSV数据的范例:
此脚本使用ConvertFrom-Csv cmdlet将内联CSV数据转换为具有与$header变量中的值匹配的属性的对象。然后使用foreach循环遍历$apps变量中的对象,并打印每个对象的属性值。
注意:在此范例中,ConvertFrom-Csv Cmdlet假设CSV数据的第一列包含信头,这就是呼叫Cmdlet时需要指定-Header参数的原因。如果您的CSV数据没有信头,您可以改用-Property参数指定属性名称。例如:
此脚本使用ConvertFrom-Csv cmdlet将内联CSV数据转换为属性与-Property参数中指定的值匹配的对象。然后,它使用foreach循环迭代$apps变量中的对象,并打印每个对象的属性值。