如何获取CSV文件中的头部信息

17
在PowerShell中,我想把CSV文件中的一个标题名称传递给PowerShell脚本中的另一个函数。如何将标题名称的值文本检索到CSV变量中?例如,如果我有以下CSV数据:
ID Name     Country
-- ----     -------
1  John     United States
2  Beatrice Germany
3  Jouni    Finland
4  Marcel   France
在上面的示例中,我该如何在我的脚本中检索Country列的值文本作为“Country”文本并存储在一个变量中?
(注意:我熟悉符号$_.Country,可以通过在Powershell中导入CSV文件来检索行的值,例如“Germany”)
我的具体问题是,目前我在我的脚本中有以下函数:
function GetItemIdFromTitle([string]$LookupTitle, [ref]$LookupId)
{   
    $LookupField = $LookupList.Fields["DEPTCATEGORY"]   
    $LookupItem = $LookupList.Items | where {$_['DEPTCATEGORY'] -like "*$LookupTitle*"} 
    $LookupId.Value = $LookupItem.ID
}

目前的代码使用字符串变量$LookupTitle在SharePoint列表中查找一个项目,并且你可以在脚本中看到我硬编码了列名为"DEPTCATEGORY"。这是在SharePoint列表中进行查找的列名。

我希望能够传入对应$LookupTitle值的列名,而不是硬编码"DEPTCATEGORY"。

以下是我调用上述函数的方式:

#GET THE LOOKUP COLUMN ID       
GetItemIdFromTitle $_.DEPTCAT ([ref]$LookupIdValue)

( $_.DEPTCAT是CSV列中行的值。)

我可以做这样的事情吗?

$myCountryColumnName = $_.Country.Property.Title 
或者
$myCategoryColumnName = $_.DEPTCAT.Property.Name

如何从CSV中获取列名?

6个回答

30
假设已经使用Import-CSV命令读取了CSV文件,您可以查看生成对象的属性。类似于此答案,但结果数组保留列顺序
检查第一行/元素。
$data = import-csv $path
$data[0].psobject.properties.name

所以第二行将返回一个属性的字符串数组。


这比@ojk的响应更好,因为它更高效,减少了CPU周期。谢谢! - Elliot Huffman

27

如果你有一个存储在 $obj 变量中的对象,你可以像这样列出所有属性头:

$obj | Get-member -MemberType 'NoteProperty' | Select-Object -ExpandProperty 'Name'

这是一个数组,因此您可以像这样单独引用它们:

($obj | Get-member -MemberType 'NoteProperty' | Select-Object -ExpandProperty 'Name')[0]

例如,这只会给你第一个属性的名称。


我正在循环CSV中的行,因此需要获取行中相应值的列名,然后将该列名传递给一个函数。 - motionpotion
我不太明白你想做什么。如果你正在遍历行并访问值,则需要属性名称才能这样做。你能给我一个更详细的例子,说明你想做什么吗? - ojk
请尝试修改后的答案。 - Raf
我在我的问题中添加了一个更具体的例子。 - motionpotion
1
好的,所以你基本上想要从属性值中查找属性名称?我不确定这是否可能,并且我不明白为什么你需要它。在你的一个例子中:$myCountryColumnName = $_.Country.Property.Title,所涉及的属性名称是Country,但是你已经有了它,因为你正在使用$_.Country,那么为什么不能只使用$myCountryColumnName = 'Country'呢? - ojk
因为我想从CSV文件中的列名获取它。在我不知道列名但仍需要导入CSV文件的情况下,这将非常有用。这将使脚本更加通用,而不是在脚本中硬编码列名。 - motionpotion

7
要从csv文件中获取列名,首先,将列标题的名称放入一个数组中(这样也可以让您在需要时循环遍历每个列)...
$inFilePath = "C:\path\to\file.csv"
$csvColumnNames = (Get-Content $inFilePath | Select-Object -First 1).Split(",")

首先,按列位置(索引从0开始)进入数组。以您的原始示例为例,应为;

$myCountryColumnName = $csvColumnNames[2]

4
提醒一下,这个解决方案不符合RFC-4180标准。如果CSV中包含逗号的转义文本,它将会出现错误。 https://tools.ietf.org/html/rfc4180 - Joe the Coder

3
这里更多是一般性的评论而非答案。
我需要从CSV文件中提取第一列标题名称,因此开始选择从Get-Member中选择NoteProperty字段。但这种方法不起作用,因为NoteProperty列头名称的顺序可能与CSV文件中的列头顺序不匹配。
futureSPQR的方法将在任何时候都有效,因为文本不会被重新排序。下面是他的方法的一行版本,用于获取第一列标题名称。
((Get-Content filename.csv)[0] -split(','))[0]

这假设 CSV 文件不会有 export-csv 默认添加的类型头。如果 CSV 没有那个类型头,你就可以开始了 :) - Elliot Huffman

0
$f = Import-Csv "...csv"

Get-Member -InputObject $f[0] |
  Where-Object {$_.MemberType -eq "NoteProperty"} |
  select-object Name

0
如果您想检查一个头部名称是否存在于数组中,请使用以下代码。
$Array | Get-member -MemberType 'NoteProperty'| where {$_.Name -eq "ColumnName"}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接