Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/perl/11.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/powershell/11.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
使用Perl或Powershell,如何比较2个CSV文件并仅获取新行?_Perl_Powershell_Csv_Compare_Diff - Fatal编程技术网

使用Perl或Powershell,如何比较2个CSV文件并仅获取新行?

使用Perl或Powershell,如何比较2个CSV文件并仅获取新行?,perl,powershell,csv,compare,diff,Perl,Powershell,Csv,Compare,Diff,我正在使用 Perl模块。 Perl程序是从.bat文件调用的,我将结果放入第三个文件Diff.csv Perl #/usr/bin/env perl 严格使用; 使用警告; 使用Text::Diff; 我的$diff=diff$ARGV[0]=>$ARGV[1]; $diff=~s/^(?:[^\n]*+\n){2}/; $diff=~s/^(?:[\@][^\n]*+)?+\n//mg; 打印$diff; 以下是我如何调用Perl脚本: perl“C:\diffBetweenTwoFile

我正在使用 Perl模块。 Perl程序是从
.bat
文件调用的,我将结果放入第三个文件
Diff.csv

Perl
#/usr/bin/env perl
严格使用;
使用警告;
使用Text::Diff;
我的$diff=diff$ARGV[0]=>$ARGV[1];
$diff=~s/^(?:[^\n]*+\n){2}/;
$diff=~s/^(?:[\@][^\n]*+)?+\n//mg;
打印$diff;
以下是我如何调用Perl脚本:

perl“C:\diffBetweenTwoFiles.pl”“C:\File1.csv”“C:\File2.csv”>“C:\Diff.csv”
CSV文件中的一列是
Name

目前,结果列出了所有列中的值发生变化的行,但我只想列出新的
Name

例如:

File1.csv
“姓名”、“出生日期”、“地址”
“一号”、“1/1/01号”、“5号股票道”
“两个”、“1/2/02”、“研究路1号”
文件2.csv
“姓名”、“出生日期”、“地址”
“一号”、“1/1/01号”、“5号股票道”
"二号,"二号,"二号,"二号,"二号,"二号,"二号,"一号,"二号,"研究道111号
“三次”、“2003年1月3日”、“三次加粗”
目前,结果列表如下(包括“两个”,因为其地址已更改):

“姓名”、“出生日期”、“地址”
"二号,"二号,"二号,"二号,"二号,"二号,"二号,"一号
“三次”、“2003年1月3日”、“三次加粗”
但是,我只希望结果列出新的“名称”,如下所示:

“姓名”、“出生日期”、“地址”
“三次”、“2003年1月3日”、“三次加粗”
如何在Perl或Powershell脚本中实现这一点?

在Perl中使用

如果在列表上下文中调用子对象,则返回true。因此,调用方通过在列表或标量上下文中调用sub来决定,
my($v1,$v2)=f(…)
my$v=f(…)
,在这种情况下,调用中不需要标志。我选择了更明确的方式

  • 名称列表中的差异在
    new_names
    sub中产生。首先,对“old”arrayref中的所有名称进行查找哈希。然后过滤“new”arrayref中的行,将那些在“old”中没有名称的行(哈希中没有这样的键),并以arrayref
    []
    的形式返回

    这种散列的使用是查找数组之间差异的标准技术


  • 用于打印的文档化方法
    say
    在我的旧版本的模块上不起作用。在这种情况下,请使用
    打印
    并在构造函数中进行设置。

    由于您处理的大文件会增加内存限制,您可以尝试:

  • 每次读取一行第一个CSV文件,并使用哈希表存储文件名条目
  • 一次读取一行第二个CSV文件,并将其名称条目与第一个进行比较
  • 根据评论更新了)PowerShell中的一个简单示例:

    $output = New-Object System.Text.StringBuilder;
    $file1 = @{};
    $header = $null;
    
    # $filePaths is two-element array with full path to CSV files
    for ($i = 0; $i -lt $filePaths.Length; ++$i) {
        $reader = New-Object System.IO.StreamReader($filePaths[$i]);
        while (($line = $reader.ReadLine()) -ne $null) {
            if ($line -match '\S') {
                if ($header -eq $null) { 
                    $header = $line;
                    $output.AppendLine($line) | Out-Null; 
                }
                $name = ($line -split ',')[0];
                switch ($i) {
                    0 { $file1.Add($name, $null); }
                    1 { 
                        if (!$file1.ContainsKey($name)) { 
                            $output.AppendLine($line) | Out-Null; 
                        } 
                    }
                }
            }
        }
        $reader.Dispose();
    }
    $output.ToString() | Out-File -FilePath $outPath;
    

    在Powershell中,您需要使用
    导入csv
    导入csv。然后可以使用
    比较对象
    进行比较。您可以从那里
    导出CSV
    (或任何您想要的格式)。如果要筛选出所需的匹配项,可以使用
    | Where Object
    。这应该给你一个好的起点。一旦您尝试了自己的解决方案,并且无法使用更新的脚本更新OP。那么我们可以帮你。谢谢你的回复。我以前尝试过使用Compare对象,但由于文件太大,它耗尽了我机器上的所有RAM,从未完成。是否有其他方法可以做到这一点,例如使用Perl?上面的Perl脚本可以工作,除了我只需要新的“Name”行。如果您使用Perl创建输出,我认为使用Perl将是最好的选择。建立所需输出的某种条件可能就是您所寻找的。不幸的是,我对Perl不够精通,无法为您提供使用Perl的解决方案的最佳路径。以下是适合您的用例的解决方案。这些“大文件”到底有多大?它们分类了吗?我认为很明显,比较CSV文件的各个字段超出了
    Text::Diff
    ,您需要编写一些特定的代码。谢谢zdim。它给了我错误“在@INC.中找不到类/CSV.pm”。我在3个不同的位置找到了CSV.pm:C:\Perl64\lib\SQL\dialogs\CSV.pm、C:\Perl64\lib\DBD\CSV.pm和C:\Perl64\lib\Bundle\DBD\CSV.pm。我在程序本身中使用lib命令添加搜索路径,如下所示,但仍然得到相同的错误:#/usr/bin/env perl使用lib'C:\Perl64\lib\Bundle\DBD';使用Class::CSV;使用Text::CSV;另外,在您的代码中,我是否将File1 File2 Diff替换为c:\File1.txt c:\File2.txt和c:\Diff.csv?前两个文件实际上是一个TXT文件,但逗号分隔,就像CSV文件一样。@faujong-ugh,模块的安装有些混乱。(这是值得澄清的,因为这只是CSV的一个转到模块。)至于文件名,您可以每行列出一个,因为您的第三个文件具有不同的扩展名,这可能更简单。您知道我如何修复“在@INC中找不到class/CSV.pm”错误吗?对于文件名,您是想这样列出它们吗?my$file_old=“c:\File1.txt”;my$file_new=“c:\File2.txt”;我的$file_diff=“c:\diff.csv”;(要替换这一行my($file\u old,$file\u new,$file\u diff)=map{$\u.'.csv'}qw(File1 File2 diff))?@faujong我不知道Windows安装是如何工作的,但在我的(Linux)系统上,
    csv.pm
    位于
    Text/
    目录中。也许您根本没有
    Text::CSV
    模块,而您的系统正在接收一些其他相关的模块?(还有,
    class/csv.pm
    令人担忧……它会引用“class::csv”模块?输入错误?)。我将针对此错误创建一个关于StackOverflow的不同问题。至于文件名,我理解对了吗?@kujibo谢谢。我将Write Host$line.Trim()替换为这样的文件:$writer=newobjectsystem.IO.StreamWriter(“c:\Diff.csv”);而(($line=$reader.ReadLine())-ne$null)
    return wantarray ? ( LIST ) : scalar;
    
    $output = New-Object System.Text.StringBuilder;
    $file1 = @{};
    $header = $null;
    
    # $filePaths is two-element array with full path to CSV files
    for ($i = 0; $i -lt $filePaths.Length; ++$i) {
        $reader = New-Object System.IO.StreamReader($filePaths[$i]);
        while (($line = $reader.ReadLine()) -ne $null) {
            if ($line -match '\S') {
                if ($header -eq $null) { 
                    $header = $line;
                    $output.AppendLine($line) | Out-Null; 
                }
                $name = ($line -split ',')[0];
                switch ($i) {
                    0 { $file1.Add($name, $null); }
                    1 { 
                        if (!$file1.ContainsKey($name)) { 
                            $output.AppendLine($line) | Out-Null; 
                        } 
                    }
                }
            }
        }
        $reader.Dispose();
    }
    $output.ToString() | Out-File -FilePath $outPath;