如何从文件名提取VRXXX子串并对应写入CSV列?
解决PowerShell中CSV每行匹配对应VR编号的问题
核心问题分析
你当前的代码在处理CSV行时,错误地将所有文件的VR编号一次性全部提取,导致每行都输出所有VR值。正确的做法是针对每一行的文件名单独提取对应的VR编号,而不是全局查询。
方案一:一步完成文件获取+VR提取+导出(推荐)
直接在获取文件属性的阶段就提取VR编号,无需分两次处理CSV,效率更高:
# 遍历目标路径下的所有docx文件,按子目录分组,取每个目录下最新的文件 $VRNames = Get-ChildItem -Path "C:\Users\******\*.docx" -Recurse | Group-Object DirectoryName | ForEach-Object { # 按最后修改时间倒序,取每个目录下最新的1个文件 $_.Group | Sort-Object LastWriteTime -Descending | Select-Object -First 1 | # 选择需要的属性,同时添加VR Number列 Select-Object BaseName, LastWriteTime, FullName, @{ Name = 'VR Number' Expression = { # 从当前文件的Basename中匹配VRXXX格式的子串 if ($_.BaseName -match 'VR\d{3}') { $matches[0] } } } } # 导出到CSV文件 $VRNames | Export-Csv -Path "C:\***\vrnames_final.csv" -NoTypeInformation -UseCulture
方案二:修改已有的initial.csv文件
如果已经生成了initial.csv,可以用以下代码为每行添加对应的VR编号:
# 导入现有CSV $initialCsv = Import-Csv -Path "C:\out\out\initial.csv" # 遍历每行,提取对应VR编号并添加新列 $updatedCsv = $initialCsv | ForEach-Object { # 针对当前行的Basename匹配VRXXX $vrNumber = if ($_.Basename -match 'VR\d{3}') { $matches[0] } else { $null } # 保留原有属性,添加新列 $_ | Select-Object *, @{Name='VR Number'; Expression={ $vrNumber }} } # 导出更新后的CSV $updatedCsv | Export-Csv -Path "C:\out\out\final_vrnames.csv" -NoTypeInformation -UseCulture
关键说明
- 正则表达式
VR\d{3}:匹配格式为VR+3位数字的子串,$matches[0]会返回当前匹配到的结果,确保每行只对应自己的VR编号。 - 避免全局查询:之前的代码中
$VRNo = $initial | Select-String ...是一次性提取所有VR编号,导致每行都输出全部值,现在改为针对$_(当前行对象)的Basename单独处理。 - 效率优化:方案一在获取文件时直接处理,减少了一次CSV导入导出的操作,更高效。
内容的提问来源于stack exchange,提问作者James Young
相关产品推荐
相关产品推荐

