Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/perl/10.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/8/file/3.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 在unix上使用多个搜索条件搜索大型CSV文件_Perl_File_Search_Csv - Fatal编程技术网

Perl 在unix上使用多个搜索条件搜索大型CSV文件

Perl 在unix上使用多个搜索条件搜索大型CSV文件,perl,file,search,csv,Perl,File,Search,Csv,我有几个大的CSV文件,我需要搜索1到多个参数,如果我找到一个命中我需要保存在另一个文件行。下面是一个成功运行的perl代码示例,但在5gb文件中运行速度非常慢。任何关于加快这一进程的建议都将不胜感激 #!/usr/bin/env perl use Text::CSV_XS; $numArgs = $#ARGV; #First Parameter is the input file name $Finput = $ARGV[0]; chomp($Finput); #Second Param

我有几个大的CSV文件,我需要搜索1到多个参数,如果我找到一个命中我需要保存在另一个文件行。下面是一个成功运行的perl代码示例,但在5gb文件中运行速度非常慢。任何关于加快这一进程的建议都将不胜感激

#!/usr/bin/env perl
use Text::CSV_XS;

$numArgs = $#ARGV;

#First Parameter is the input file name
$Finput = $ARGV[0];
chomp($Finput);

#Second Parameter is the output file name
$Foutput = $ARGV[1];
chomp($Foutput);

# Open the Control file but quit if it doesn't exist
open(INPUT1, $Finput) or die "The Input File $Finput could not be found.\n";
open(OUTPUT1, ">$Foutput") or die "Cannot open output $Foutout file.\n";


my $csv = Text::CSV_XS->new();
open my $FH, "<", $Finput;

while (<$FH>) {
    $csv->parse($_);
    my @fields = $csv->fields;

    if ($fields[0] == 10000) {
        if ($fields[34] eq 'abcdef') {
            if ($fields[103] == 9999) {
                print OUTPUT1 "$_\n";
            }
        }
    }
}
#/usr/bin/env perl
使用Text::csvxs;
$numArgs=$#ARGV;
#第一个参数是输入文件名
$Finput=$ARGV[0];
chomp($Finput);
#第二个参数是输出文件名
$Foutput=$ARGV[1];
chomp($Foutput);
#打开控制文件,如果不存在则退出
打开(INPUT1,$Finput)或关闭“找不到输入文件$Finput。\n”;
打开(OUTPUT1“>$Foutput”)或死“无法打开输出$Foutout文件。\n”;
my$csv=Text::csv_XS->new();

打开我的$FH,“我不知道您的数据或标准

但是,如果我们可以使用上面给出的示例,那么我会在执行CSV处理之前尝试对行进行简单的测试

例如(注意,我的perl很糟糕,这是示例,不正确):

基本上,在执行鉴定行所需的附加处理之前,您可以执行一些更简单、更快的检查,以更快地取消鉴定行

显然,如果您的行中匹配的行比不匹配的行多,或者如果简单限定的检查实际上不实用,那么这种技术将不起作用

如果做得好,CSV解析会有点昂贵(事实上,假设一行CSV是一条记录,这对您的数据可能是正确的,但CSV实际上允许嵌入换行符,因此这不是一个可以对所有CSV进行的通用假设)

因此,如果“一目了然”该行无论如何都不匹配,那么不必为解析它付出代价是很好的。

您想在每个文件上使用grep“{searchstring}”filename1.csv filename2.csv>savefile.txt。也许您想逐行读取filename.csv:

#!/bin/bash
exec 3<filename.csv
while read haystack <&3
do
  grep "{needle}" $haystack > result.txt 
done
!/bin/bash
exec 3这是“成功”运行的代码?我觉得很难相信

if ($fields[0] = 10000) {
    if ($fields[34] = 'abcdef') {
        if ($fields[103] = 9999) {
这些不是相等的检查,而是赋值。所有这些if子句都将始终返回true。这里您可能想要的是
=
eq
,而不是
=

您还打开了输入文件上的两个文件句柄,并以错误的方式使用了CSV模块。我不认为这些小错误会导致脚本速度太慢,但它会打印该5gb文件中的所有记录

这是你剧本的修订版

use strict;
use warnings;
use Text::CSV;
use autodie;

my $Finput = $ARGV[0];
my $Foutput = $ARGV[1];

open my $FH, "<", $Finput;
open my $out, ">", $Foutput;

my $csv = Text::CSV->new();

while (my $row = $csv->getline($FH)) {
    my @fields = @$row;
    if ($fields[0] == 10000) {
        if ($fields[34] eq 'abcdef') {
            if ($fields[103] == 9999) {
                $csv->print($out, $row);
            }
        }
    }
}
使用严格;
使用警告;
使用Text::CSV;
使用自动模具;
my$Finput=$ARGV[0];
my$Foutput=$ARGV[1];
打开我的$FH,“,$Foutput;
my$csv=Text::csv->new();
while(my$row=$csv->getline($FH)){
我的@fields=@$行;
如果($fields[0]==10000){
如果($fields[34]等式'abcdef'){
如果($fields[103]==9999){
$csv->打印($out,$row);
}
}
}
}

autodie
pragma将为我们(和其他事物)检查
open
的返回值。
使用严格;使用警告;
将减少我们的大脑伤害。哦,我正在使用,而不是XS版本。

如果($fields[0]=10000)
如果($fields[34]='abcdef'))
可能没有按照您的想法进行操作。您可能需要
==
运算符(用于数字比较)以及用于字符串比较的
eq
运算符。很难想象这段代码实际上能以其发布的方式正确工作。在示例代码中,您也从未阅读过
INPUT1
。要获得真正准确的答案,我们需要知道您现有的(工作)代码算法看起来像什么,或者你的输入和输出数据应该是什么样子。由于发布的代码不能准确地表示你实际成功但运行缓慢的内容,我们只能猜测你真正需要什么。感谢DavidO…我更正了运算符,并且在调用此脚本时接受2个参数,所以我这样运行它。…perl script.pls继续思考…所以我像这样运行它…perl script.pl input_file.csv out_putfile.csv…这会读入第一个文件并循环通过它,如果找到,会生成第二个文件。输入日期如下…(2011071804371910000,“名称,关联”,1110101,,I,1,1,USA,USA……新行,然后另一行2011071804371910000,“名称,关联”,1110101,,I,1,1,USA,USA)。如果找到匹配项,我们应该将整行复制到新文件中。grep或egrep可以工作,但是否有方法生成这些命令,并确保当它在csv行的103位置而不是其他位置(如50)找到9999时,我得到命中?我明白你在解析前的预验证上的观点,让我试试看是否可以节省一些时间。我怀疑在包含数百个字段的行上执行正则表达式搜索会比if中的更快。综合起来,每行的整个过程可能会慢一些,但基本前提是,伪行比t多rue行,所以总体来说速度更快。没有什么说你必须检查所有字段,一个简单的10000行测试可能足以拒绝大多数行。perl中的正则表达式是用C编写的,非常快,我不知道CSV模块是用C编写的,但很可能是用perl编写的。CSV模块必然会创建很多行如果行被拒绝,则不需要的数据(例如字段)。如果字段中不可能嵌入
\n
,这是一个很好的建议。但是将regexp分解为三个较小的匹配项会更有效。例如:
if(/\D10000\D/和/\babcdef\b/和/\D9999\D/){$csv->parse($);…
。目标是三个小的易于匹配的regexp,它们永远不会有任何回溯复杂性。如果regexp不检查字段顺序,这真的不重要。目标只是拒绝大部分“不可能”行,并且
use strict;
use warnings;
use Text::CSV;
use autodie;

my $Finput = $ARGV[0];
my $Foutput = $ARGV[1];

open my $FH, "<", $Finput;
open my $out, ">", $Foutput;

my $csv = Text::CSV->new();

while (my $row = $csv->getline($FH)) {
    my @fields = @$row;
    if ($fields[0] == 10000) {
        if ($fields[34] eq 'abcdef') {
            if ($fields[103] == 9999) {
                $csv->print($out, $row);
            }
        }
    }
}