在Powershell中选择CSV列,其中标题名称包含特定字符串
我有一个数据文件,其中包含大约10-15列,我想从中提取特定列。一些列我知道确切的列标题和其他人我只知道前两个字母将永远是“FC”。 如何仅选择我知道列标题的列和那些以“FC”开头的列? 只用 “FC” 栏目开始,我已经试过这样:在Powershell中选择CSV列,其中标题名称包含特定字符串
$myCSV = Import-CSV "mydata.txt" -Delimiter "`t"
$FCcols = $myCSV[0].psobject.Properties | foreach { $_.Name } | Where {$_ -match "FC"}
$myCSV | select $FCcols
但我只是得到一个错误:
Select-Object : Cannot convert System.Management.Automation.PSObject to one of
the following types {System.String, System.Management.Automation.ScriptBlock}.
At line:3 char:16
+ $myCSV | select <<<< $FCcols
+ CategoryInfo : InvalidArgument: (:) [Select-Object], NotSupport
edException
+ FullyQualifiedErrorId : DictionaryKeyUnknownType,Microsoft.PowerShell.Co
mmands.SelectObjectCommand
然后,如果我尝试:
$myCSV = Import-CSV "mydata.txt" -Delimiter "`t"
$FCcols = [System.Collections.ArrayList]@()
$myCSV[0].psobject.Properties | foreach { $_.Name } | Where {$_ -match "FC"} | %{$FCcols.Add($_)}
$myCSV | select $FCcols
我得到我想要的输出,除了它是“列标题:值”格式,如下所示:
FC1839 : 0
FC1842 : 1
FC1843 : 6
FC1844 : 12
FC1845 : 4
FC1839 : 0
FC1842 : 0
FC1843 : 19
FC1844 : 22
FC1845 : 14
我可能只是错过了一些简单的事情,但我如何才能够选择这些匹配的列,然后将它们输出到另一个.txt文件(不使用header:value格式)?
首先第一件事情:Mathias R. Jessen's有用的提示,不仅解决您的问题,但显著简化的方法(也工作在PSV2):
$myCSV | Select-Object FC*
的(隐含的)-Property
参数支持通配符表达式,所以FC*
匹配以FC
开头的所有属性(列名称)。
至于你所看到的输出格式:因为你要选择的5个属性,PowerShell的默认值为implicit Format-List
格式,在其自己的行每个属性名称 - 值对。
要修复此显示问题,管Format-Table
明确(这是什么PowerShell中会暗中做,如果你已经选择4个或更少的属性):
$myCSV | Select-Object FC* | Format-Table
要转口结果到CSV(TSV)文件:
Import-Csv mydata.txt -Delimiter "`t" | Select-Object FC* |
Export-Csv myresults.txt -Encoding Utf8 -Delimiter "`t" -NoTypeInformation
为此无头立NE:
Import-Csv mydata.txt -Delimiter "`t" | Select-Object FC* |
ConvertTo-Csv -Delimiter "`t" -NoTypeInformation | Select-Object -Skip 1 |
Set-Content myresults.txt -Encoding Utf8
至于您的具体症状:
只发生在PSV2的问题,它闻起来像我的错误。
的解决方法是让你的列名数组强类型串阵列([string[]]
):
[string[]] $FCcols = $myCSV[0].psobject.Properties | % { $_.Name } | ? { $_ -match '^FC' }
需要注意的是,为了简便起见,我用内置别名%
在代替ForEach-Object
和?
代替Where-Object
。
另请注意,传递给-match
的正则表达式更改为^FC
,以确保只匹配开始的列与FC
匹配。
你代码工作,是在PSv3 +,但可以简化:
$FCcols = $myCSV[0].psobject.Properties.Name -match "^FC"
注.Name
如何直接应用于.psobject.Properties
,这在V3 +的.Name
成员导致被调用集合中的每个项目,称为member enumeration的特征。
Mathias的有用评论是最好的选择方式;简单而优雅 - 不知道这是一个选择。
$myCSV | Select *FC*,ColumnIKnowTheNameOf
我相信你需要添加Export-Csv
回答你的最后一个问题。如果您将来需要查询csv /类似对象,那么我已经使用了另一种方法,它使用Get-Member
和NoteProperty
。
$myCSV = Import-CSV "mydata.txt" -Delimiter "`t"
# you can get the headings by using Get-Member and Selecting NoteProperty members.
$FCcols = $myCSV |
Get-Member |
Where-Object {$_.MemberType -eq "NoteProperty" -and $_.Name -match "FC"} |
Select-Object -ExpandProperty Name
# you add names to this array.
$FCcols += "ColumnIKnowTheNameOf"
$myCSV | Select-Object $FCcols
# to get a tab-delimited file similar to the one you imported, use Export-Csv
$myCSV | Export-csv "myresults.txt" -Delimiter "`t" -NoTypeInformation
我会用Get-Member
让你的栏目,像这样:
$myCSV = Import-CSV "mydata.txt" -Delimiter "`t"
$myCSV | select ($myCSV | gm -MemberType NoteProperty | ? {$_.Name -match 'FC'}).Name
谢谢你的回应。虽然它没有完全解决我的问题,但我能够在其他地方使用它。一个非常有用的技术。 –
我终于有一个“快速和肮脏”的解决方案,我很失望,走到不能早点想通了。
$myCSV = Import-CSV "mydata.txt" -Delimiter "`t" | select FC*
for ($i = 0; $i -lt $myCSV.count; $i++){
$writeline = ($myCSV[$i] | %{$_.PSObject.Properties | %{$_.Value}}) -join "`t"
ac "myresults.txt" $writeline -Encoding utf8}
第一行给我我想要的列,那么for循环获取每个列的值的属性,并加入他们的表格线,最后每行追加到一个文本文件中。 这可能不是达到结果的教学方法正确的方法,但它的工作至今。 感谢大家的意见!
快速干净的解决方案如何提高内存效率? 'Import-Csv mydata.txt -Delimiter“\'t”|选择对象FC * | Export-Csv myresults。txt -Encoding Utf8 -Delimiter“\'t”-NoTypeInformation“(如果你真的不想要标题行,将ConvertTo-Csv和Select-Object -Skip结合起来并将其转换为Set-Content) 。 另外,未来的读者会感到困惑的是,您的答案中添加的唯一新东西超过了现有答案,就是解决了您没有要求在问题中解决的问题(重新导出为CSV/TSV)。 – mklement0
对话最终涉及许多问题,因此变得混乱,但出口到文本文件确实是最初目标的一部分。输出格式导致出口困难。我选择包含此解决方案,因为它解决了原始任务,包括格式化的困难以及能够以“FC”开头的列名选择。 –
我很抱歉,如果选择这个解决方案似乎否定其他输入。这不是意图。来自Mathias R. Jessen,mklement0和Dave Sexton的意见对我能够解决这个问题起到了重要作用。如果看起来更合适,我可以将Mathias R Jessen的答案改为官方解决方案。 –
为什么不只是'$ myCSV | Select * FC *'? –
如果您使用$ myCSV |,您将拥有什么功能选择$ FCcols.Name但Mathias是正确的... – bunzab
@bunzab:的确,Mathias的方法是最好的解决方案。 '$ FCcols.Name'不起作用,因为'$ FCcols'是一个_strings_(没有'.Name'属性)的数组。事实上,由于我认为是一个错误,代码在PSv3 +中原样运行,并且仅在PSv2中失败。 – mklement0