Arrays 分析带引号字段的字符串,如Powershell中的CSV行
我必须将变量输入字符串解析为字符串数组。 输入是CSV样式的逗号分隔字段列表,其中每个字段都有自己的带引号的字符串。 因为我不想编写自己完整的CSV解析器,所以到目前为止,我唯一可以创建的工作解决方案是:Arrays 分析带引号字段的字符串,如Powershell中的CSV行,arrays,powershell,csv,Arrays,Powershell,Csv,我必须将变量输入字符串解析为字符串数组。 输入是CSV样式的逗号分隔字段列表,其中每个字段都有自己的带引号的字符串。 因为我不想编写自己完整的CSV解析器,所以到目前为止,我唯一可以创建的工作解决方案是: $input = '"Miller, Steve", "Zappa, Frank", "Johnson, Earvin ""Magic"""' Add-Type -AssemblyName M
$input = '"Miller, Steve", "Zappa, Frank", "Johnson, Earvin ""Magic"""'
Add-Type -AssemblyName Microsoft.VisualBasic
$enc = [System.Text.Encoding]::UTF8
$bytes = $enc.GetBytes($input)
$stream = [System.IO.MemoryStream]::new($bytes)
$parser = [Microsoft.VisualBasic.FileIO.TextFieldParser]::new($stream)
$parser.Delimiters = ','
$parser.HasFieldsEnclosedInQuotes = $true
$list = $parser.ReadFields()
$list
输出如下所示:
Miller, Steve
Zappa, Frank
Johnson, Earvin "Magic"
是否有更好的解决方案可通过另一个.NET库用于Powersell?
在最好的情况下,我可以避免这个额外的字节数组和流。
我也不确定这个视觉基础组件是否会长期有效
有什么想法吗?为了安全和防止无意中的字符串外推,您可以与结合使用,不过请注意:
$fieldList='“米勒,史蒂夫”,“扎帕,弗兰克”,“约翰逊,埃尔文”,“魔术”,“亲爱的,我是$HOME”
#解析为数组。
$fields=(
调用表达式(“写入输出”+($fieldList-替换“\$”,“`0”))
)-替换“`0”,“$$”
注:
临时替换文字-替换“\$”,“`0”
字符。在具有NUL字符的输入中。防止意外(或恶意);第二个$
操作恢复原始-replace
字符。$
有关基于正则表达式的
运算符的更多信息,请参阅-replace
- 如果仅当输入字符串保证不包含嵌入的
字符时,解决方案可以简化为:$
$fields = Invoke-Expression "Write-Output $fieldList"
$fields
会产生以下结果:
史提夫·米勒
扎帕,弗兰克
约翰逊,埃尔文“魔术”
亲爱的,我回家了
说明和约束列表: 解决方案依赖于使输入字符串成为字符串的一部分,该字符串的内容在语法上是有效的
Write-Output
调用,输入字符串用作后者的参数Invoke Expression
然后对该字符串求值,就好像它的内容是作为命令直接提交的一样,并因此执行Write Output
命令。根据PowerShell解析命令参数的方式,这意味着以下约束:
- 支持的字段分隔符:
- 或者:
-分隔的(删除每个字段(无引号)的前导和/或尾随空格,如上所示),
- 或者:空格分隔,在字段之间使用一个或多个空格字符
- 或者:
- 不引用嵌入字段:
- 可以引用以下字段:
- 如果单引号(
),字段内部“…”
字符必须作为“
转义”
- 如果双引号,字段内部的
字符必须作为“
或”
转义`
- 如果单引号(
- 字段也可以不带引号:
- 但是,此类字段不得包含任何PowerShell参数模式元字符(其中,
仅是令牌开头的元字符):<>@#
如果列表有限,则可以使用cmdlet的解析器,如:$List = '"Miller, Steve", "Zappa, Frank", "Johnson, Earvin ""Magic""", "Honey, I''m $HOME"' ($List | ConvertFrom-Csv -Header (0..99)).PSObject.Properties.Value.Where{ $Null -ne $_ } Miller, Steve Zappa, Frank Johnson, Earvin "Magic" Honey, I'm $HOME
+1对于这个想法,尽管
部分有点笨拙。一个简单的解决方案是提供两次输入字符串:-Header(0..99)
提交两次输入字符串对于解决未知数量的列名来说是非常明智的($List,$List | ConvertFrom Csv).psobject.Properties.Value
$List = '"Miller, Steve", "Zappa, Frank", "Johnson, Earvin ""Magic""", "Honey, I''m $HOME"' ($List | ConvertFrom-Csv -Header (0..99)).PSObject.Properties.Value.Where{ $Null -ne $_ } Miller, Steve Zappa, Frank Johnson, Earvin "Magic" Honey, I'm $HOME
- 但是,此类字段不得包含任何PowerShell参数模式元字符(其中,
- 可以引用以下字段: