PowerShell中使用Select-Object处理CSV动态列名问题
使用正则表达式动态重命名CSV中的月份相关列
问题场景
CSV文件里部分列名会随月份动态变化,这些列对应不同历史月份的数据,示例列名:
- Actuals(-3) Reg Hrs Oct-22
- Actuals(-2) Reg Hrs Nov-22
- Actuals(-1) Reg Hrs Dec-22
需要将这些列重命名为不带月份的通用名称,适配预配置的Schema:
- Actuals(-3) Reg Hrs
- Actuals(-2) Reg Hrs
- Actuals(-1) Reg Hrs
当前代码需要指定具体列名,无法适配动态变化的月份,希望用正则匹配静态前缀实现动态处理(假设无列名歧义),当前代码如下:
Import-Csv -Path $csvFile | where {$_."Cost Center" -eq "ABC123"} | Select-Object @{ expression={$_."Actuals(-3) Reg Hrs Oct-22"}; label='3 Months Ago Regular' } | Export-Csv -notype $csvFile2
解决方案
可以通过正则匹配列名的静态前缀,动态定位并重命名目标列,修改后的PowerShell代码如下:
# 导入并筛选目标成本中心的数据 $csvData = Import-Csv -Path $csvFile | Where-Object { $_."Cost Center" -eq "ABC123" } # 定义列名匹配规则:正则模式、新列名、导出用标签 $columnRules = @( @{ Pattern = '^Actuals\(-3\) Reg Hrs ' NewName = 'Actuals(-3) Reg Hrs' ExportLabel = '3 Months Ago Regular' }, @{ Pattern = '^Actuals\(-2\) Reg Hrs ' NewName = 'Actuals(-2) Reg Hrs' ExportLabel = '2 Months Ago Regular' }, @{ Pattern = '^Actuals\(-1\) Reg Hrs ' NewName = 'Actuals(-1) Reg Hrs' ExportLabel = '1 Month Ago Regular' } ) # 构建Select-Object的属性映射 $selectProperties = @() foreach ($rule in $columnRules) { # 找到匹配当前正则的动态列名 $matchedColumn = $csvData[0].PSObject.Properties.Name | Where-Object { $_ -match $rule.Pattern } if ($matchedColumn) { # 添加动态属性映射,确保能正确取到对应列的值 $selectProperties += @{ Expression = [scriptblock]::Create("`$_.`"$matchedColumn`"") Name = $rule.NewName # 重命名列本身(适配Schema) Label = $rule.ExportLabel # 导出文件显示的列名(可选) } } } # 保留需要的其他列,比如Cost Center,可按需调整 $selectProperties += "Cost Center" # 处理数据并导出 $csvData | Select-Object $selectProperties | Export-Csv -Path $csvFile2 -NoTypeInformation
关键说明
- 正则转义:列名里的括号是正则特殊字符,需要用
\(和\)转义,确保只匹配Actuals(-3)这类静态前缀 - 动态列匹配:通过读取CSV对象的属性名,用正则筛选出目标列,不管后面的月份如何变化都能定位到
- 属性映射:动态生成
Select-Object的表达式,保证能正确获取对应列的值,同时完成重命名
内容的提问来源于stack exchange,提问作者AJ Mieskolainen
相关产品推荐
相关产品推荐

