如何用Perl或PowerShell对比CSV文件,仅提取新增Name行?
解决方案:提取CSV中新增的Name行
你的需求是只获取File2中存在但File1中没有的Name对应的整行,而不是所有文本差异行——原来的Text::Diff是逐行文本对比,所以会把内容变更的行也列出来,这不符合你的要求。下面分别用Perl和PowerShell实现更精准的基于Name列的筛选:
方法一:用Perl实现(推荐使用Text::CSV处理CSV)
直接基于Name列的存在性对比比文本逐行对比更可靠,尤其是CSV可能包含复杂字段(比如字段内有逗号)。我们可以用Text::CSV模块来正确解析CSV,避免手动处理引号和逗号的麻烦:
Perl代码
#!/usr/bin/env perl use strict; use warnings; use Text::CSV; # 初始化CSV解析器,处理带引号的字段 my $csv = Text::CSV->new({ binary => 1, auto_diag => 1 }); # 读取File1的所有Name到哈希表,用于快速查找 my %existing_names; open my $f1_fh, '<', $ARGV[0] or die "无法打开File1: $!"; # 跳过表头 $csv->getline($f1_fh); while (my $row = $csv->getline($f1_fh)) { my $name = $row->[0]; # Name是第一列 $existing_names{$name} = 1; } close $f1_fh; # 遍历File2,输出Name不在File1中的行 open my $f2_fh, '<', $ARGV[1] or die "无法打开File2: $!"; # 先输出表头(如果需要的话) my $header = $csv->getline($f2_fh); $csv->print(\*STDOUT, $header); print "\n"; while (my $row = $csv->getline($f2_fh)) { my $name = $row->[0]; unless (exists $existing_names{$name}) { $csv->print(\*STDOUT, $row); print "\n"; } } close $f2_fh;
调用方式
和之前一样,通过bat或者直接命令行调用,输出到Diff.csv:
perl "C:\diffBetweenTwoFiles.pl" "C:\File1.csv" "C:\File2.csv" > "C:\Diff.csv"
如果不想安装Text::CSV模块(虽然强烈推荐),也可以用正则提取Name字段,但要注意仅适用于Name字段格式统一的情况:
#!/usr/bin/env perl use strict; use warnings; my %existing_names; open my $f1_fh, '<', $ARGV[0] or die "无法打开File1: $!"; <$f1_fh>; # 跳过表头 while (<$f1_fh>) { if (/^"([^"]+)"/) { # 提取第一个带引号的字段作为Name $existing_names{$1} = 1; } } close $f1_fh; open my $f2_fh, '<', $ARGV[1] or die "无法打开File2: $!"; print scalar <$f2_fh>; # 输出表头 while (<$f2_fh>) { if (/^"([^"]+)"/ && !exists $existing_names{$1}) { print $_; } } close $f2_fh;
方法二:用PowerShell实现
PowerShell处理CSV非常便捷,不需要额外安装模块,直接用内置命令即可:
PowerShell命令
# 读取两个CSV文件 $file1 = Import-Csv -Path "C:\File1.csv" $file2 = Import-Csv -Path "C:\File2.csv" # 筛选File2中Name不在File1里的行,导出到Diff.csv $file2 | Where-Object { $file1.Name -notcontains $_.Name } | Export-Csv -Path "C:\Diff.csv" -NoTypeInformation
说明
Import-Csv会自动解析CSV的表头和字段,不需要手动处理引号。-NoTypeInformation参数避免在导出的CSV开头添加PowerShell的类型信息(比如#TYPE System.Management.Automation.PSCustomObject)。- 如果要通过bat调用PowerShell,可以写如下bat脚本:
powershell -Command "$file1 = Import-Csv 'C:\File1.csv'; $file2 = Import-Csv 'C:\File2.csv'; $file2 | Where-Object { $file1.Name -notcontains $_.Name } | Export-Csv 'C:\Diff.csv' -NoTypeInformation"
内容的提问来源于stack exchange,提问作者faujong
相关产品推荐
相关产品推荐

