Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/php/274.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
Php 将多个csv文件组合在一起,并在连接过程中添加列_Php_Python_Perl_Powershell_Awk - Fatal编程技术网

Php 将多个csv文件组合在一起,并在连接过程中添加列

Php 将多个csv文件组合在一起,并在连接过程中添加列,php,python,perl,powershell,awk,Php,Python,Perl,Powershell,Awk,我有一组文件正试图导入MySQL 每个CSV文件如下所示: use DBI; my $DBH = DBI->connect ("dbi:CSV:", "", "", { f_dir => "$DATABASEDIR", f_ext => ".csv", csv_sep_char => ";",}); my $sth = $dbh->prepare ("SELECT * FROM Token1_Token2_Token3"); $sth->execute; wh

我有一组文件正试图导入MySQL

每个CSV文件如下所示:

use DBI;
my $DBH = DBI->connect ("dbi:CSV:", "", "", { f_dir => "$DATABASEDIR", f_ext => ".csv", csv_sep_char => ";",});
my $sth = $dbh->prepare ("SELECT * FROM Token1_Token2_Token3");
$sth->execute;
while (my $hr = $sth->fetchrow_hashref) {

 [...]
}
$sth->finish ();
校长1;校长2;校长3;校长4;校长5 数据1;数据2;数据3;数据4;数据5; 数据1;数据2;数据3;数据4;数据5; 数据1;数据2;数据3;数据4;数据5; 数据1;数据2;数据3;数据4;数据5; 数据可以包含空格、句点或完整的冒号。它们绝对不包含分号,因此分号是有效的分隔符。它们也不包含\n或任何其他换行符

示例数据 2010.08.30 18:34:59 0.7508 包含空格的字符串 每个文件都有一个唯一的名称。所有名称均符合以下模式: 令牌1\u令牌2\u令牌3.csv

我感兴趣的是将数百个CSV文件组合成一个CSV文件。文件大小可以从10KB到400MB。最后,我想把它发送到MySQL。不要担心去掉单独的标题行;我可以在MySQL中轻松做到这一点

我希望最终的CSV文件如下所示:

use DBI;
my $DBH = DBI->connect ("dbi:CSV:", "", "", { f_dir => "$DATABASEDIR", f_ext => ".csv", csv_sep_char => ";",});
my $sth = $dbh->prepare ("SELECT * FROM Token1_Token2_Token3");
$sth->execute;
while (my $hr = $sth->fetchrow_hashref) {

 [...]
}
$sth->finish ();
Header1,Header2,Header3,Header4,Header5,文件名 数据1、数据2、数据3、数据4、数据5、令牌1 数据1、数据2、数据3、数据4、数据5、令牌1 数据1、数据2、数据3、数据4、数据5、令牌1 数据1、数据2、数据3、数据4、数据5、令牌1 数据1、数据2、数据3、数据4、数据5、令牌1 我不在乎任何其他代币。如果解决方案只是将每个csv文件名转储到Token1字段中,我也可以活下来,因为我可以在MySQL中轻松解析它

请帮帮我!我花了10个多小时研究了一个相对容易的问题

现有技术:

awk windows批处理 linux bash 动力壳 perl 蟒蛇 php mysql导入


这是一个服务器盒,因此我无法编译任何内容,但如果您给我一个Java解决方案,我肯定会尝试在服务器盒上运行它。

您可能希望尝试这种快速且肮脏的Perl黑客来转换数据:

#!/usr/bin/perl
use strict;
use warnings;

# Open input file
my $inputfile = shift or die("Usage: $0 <filename>\n\n");
open F, $inputfile or die("Could not open input file ($!)\n\n");

# Split filename into an array
my @tokens = split("_", $inputfile);

my $isFirstline = 1;

# Iterate each line in the file
foreach my $line (<F>) {
    my $addition;

    chomp($line);    # Remove newline

    # Add the complete filename to the line at first line
    if ($isFirstline) {
        $isFirstline = 0;
        $addition    = ",$inputfile";
    } else {         # Add first token for the rest of the lines
        $addition = ",$tokens[0]";
    }

    # Split the data into @elements array
    my @elements = split(";", $line);

    # Join it using comma and add filename/token & a new line
    print join(",", @elements) . $addition . "\n";
}

close(F);

您可能希望尝试这种快速且肮脏的Perl黑客程序来转换数据:

#!/usr/bin/perl
use strict;
use warnings;

# Open input file
my $inputfile = shift or die("Usage: $0 <filename>\n\n");
open F, $inputfile or die("Could not open input file ($!)\n\n");

# Split filename into an array
my @tokens = split("_", $inputfile);

my $isFirstline = 1;

# Iterate each line in the file
foreach my $line (<F>) {
    my $addition;

    chomp($line);    # Remove newline

    # Add the complete filename to the line at first line
    if ($isFirstline) {
        $isFirstline = 0;
        $addition    = ",$inputfile";
    } else {         # Add first token for the rest of the lines
        $addition = ",$tokens[0]";
    }

    # Split the data into @elements array
    my @elements = split(";", $line);

    # Join it using comma and add filename/token & a new line
    print join(",", @elements) . $addition . "\n";
}

close(F);
使用:

程序 使用:

程序
信不信由你,这可能很简单:

awk 'BEGIN{OFS = FS = ";"} {print $0, FILENAME}' *.csv > newfile.csv
如果要将字段分隔符从分号更改为逗号:

awk 'BEGIN{OFS = ","; FS = ";"} {$1 = $1; print $0, FILENAME}' *.csv > newfile.csv
要仅包括第一个令牌,请执行以下操作:

awk 'BEGIN{OFS = ","; FS = ";"} {$1 = $1; split(FILENAME, a, "_"); print $0, a[1]}' *.csv > newfile.csv

信不信由你,这可能很简单:

awk 'BEGIN{OFS = FS = ";"} {print $0, FILENAME}' *.csv > newfile.csv
如果要将字段分隔符从分号更改为逗号:

awk 'BEGIN{OFS = ","; FS = ";"} {$1 = $1; print $0, FILENAME}' *.csv > newfile.csv
要仅包括第一个令牌,请执行以下操作:

awk 'BEGIN{OFS = ","; FS = ";"} {$1 = $1; split(FILENAME, a, "_"); print $0, a[1]}' *.csv > newfile.csv

Perl的DBI模块可以处理CSV文件DBD::CSV模块和MySQL。只需将所有csv文件放在同一目录中,并按如下方式查询它们:

use DBI;
my $DBH = DBI->connect ("dbi:CSV:", "", "", { f_dir => "$DATABASEDIR", f_ext => ".csv", csv_sep_char => ";",});
my $sth = $dbh->prepare ("SELECT * FROM Token1_Token2_Token3");
$sth->execute;
while (my $hr = $sth->fetchrow_hashref) {

 [...]
}
$sth->finish ();

你可以查询csv文件,包括JOIN语句!并将数据直接插入MySQL。

Perl的DBI模块可以处理所需的CSV文件DBD::CSV模块和MySQL。只需将所有csv文件放在同一目录中,并按如下方式查询它们:

use DBI;
my $DBH = DBI->connect ("dbi:CSV:", "", "", { f_dir => "$DATABASEDIR", f_ext => ".csv", csv_sep_char => ";",});
my $sth = $dbh->prepare ("SELECT * FROM Token1_Token2_Token3");
$sth->execute;
while (my $hr = $sth->fetchrow_hashref) {

 [...]
}
$sth->finish ();

你可以查询csv文件,包括JOIN语句!并将数据直接插入MySQL。

这是在PowerShell中执行此操作的一种方法:

$res = 'result.csv'
'Header1,Header2,Header3,Header4,Header5,FileName' > $res

foreach ($file in dir *.csv)
{
  if ($file -notmatch '(\w+)_\w+_\w+\.csv') { continue }

  $csv = Import-Csv $file -Delimiter ';'
  $csv | Foreach {"{0},{1},{2},{3},{4},{5}" -f `
    $_.Header1,$_.Header2,$_.Header3,$_.Header4,$_.Header5,$matches[1]} >> $res
}
如果文件的大小不是那么大,我建议采用以下方法:

$csvAll = @()
foreach ($file in dir *.csv)
{
  if ($file -notmatch '(\w+)_\w+_\w+\.csv') { continue }

  $csv = Import-Csv $file -Delimiter ';'
  $csv | Add-Member NoteProperty FileName $matches[1]
  $csvAll += $csv
}

$csvAll | Export-Csv result.csv -NoTypeInformation

但是,这会将所有CSV文件的完整内容保存在内存中,直到最后可以导出为止。除非您的64位窗口具有大量内存,否则不可行:-

这是在PowerShell中执行此操作的一种方法:

$res = 'result.csv'
'Header1,Header2,Header3,Header4,Header5,FileName' > $res

foreach ($file in dir *.csv)
{
  if ($file -notmatch '(\w+)_\w+_\w+\.csv') { continue }

  $csv = Import-Csv $file -Delimiter ';'
  $csv | Foreach {"{0},{1},{2},{3},{4},{5}" -f `
    $_.Header1,$_.Header2,$_.Header3,$_.Header4,$_.Header5,$matches[1]} >> $res
}
如果文件的大小不是那么大,我建议采用以下方法:

$csvAll = @()
foreach ($file in dir *.csv)
{
  if ($file -notmatch '(\w+)_\w+_\w+\.csv') { continue }

  $csv = Import-Csv $file -Delimiter ';'
  $csv | Add-Member NoteProperty FileName $matches[1]
  $csvAll += $csv
}

$csvAll | Export-Csv result.csv -NoTypeInformation

但是,这会将所有CSV文件的完整内容保存在内存中,直到最后可以导出为止。除非您的64位窗口具有大量内存,否则不可行:-

您是否尝试过查看Python csv模块文档以读取数据文件并编写组合文件,使用str.partition方法获取文件名的第一部分?您是否尝试过查看Python csv模块文档以读取数据文件并编写组合文件,使用str.partition方法获取文件名的第一部分?Dennis-最后一个awk语句应该可以。它在测试数据上工作得非常好,我现在在20GB上运行它。出于某种原因,它在$1和拆分之间添加了一个空白的空列,但我可以在数据进入数据库后再处理这个问题。非常感谢你!!您可以单击。@jlocke:从您的示例数据来看,您的行可能以分隔符结尾,这意味着最后一个字段为空。如果是这种情况,您可以将该空字段设置为文件名,而不是附加它:awk'BEGIN{OFS=,;FS=;}{splitFILENAME,a,;$NF=a[1];print}'*.csv>newfile.csv。顺便说一下,$1是第一个字段,所以我假设您是指文件名标记之前的一个空白字段,该字段介于$0和拆分之间。$1=$1强制替换字段分隔符。此注释中的版本不需要这个选项,赋值就可以了。@jlocke:记住,您可以通过a2p为awk程序提供一个等价的Perl,这个值比其他多余的答案要短得多!如果您有更多此类任务,我建议
d花几个小时学习AWK,它真的会把它们钉牢;我认为BEGIN{OFS=,;FS=;}FNR>1 | | NR==FNR{$1=$1;splitFILENAME,a,;print$0,a[1]}未经测试可以解决这个问题。更妙的是,只需去掉所有标题FNR>1-自动处理文件而无需标题行要容易得多。@BeniCherniavsky Paskin:好建议。Dennis-最后一条awk语句应该可以做到这一点。它在测试数据上工作得非常好,我现在在20GB上运行它。出于某种原因,它在$1和拆分之间添加了一个空白的空列,但我可以在数据进入数据库后再处理这个问题。非常感谢你!!您可以单击。@jlocke:从您的示例数据来看,您的行可能以分隔符结尾,这意味着最后一个字段为空。如果是这种情况,您可以将该空字段设置为文件名,而不是附加它:awk'BEGIN{OFS=,;FS=;}{splitFILENAME,a,;$NF=a[1];print}'*.csv>newfile.csv。顺便说一下,$1是第一个字段,所以我假设您是指文件名标记之前的一个空白字段,该字段介于$0和拆分之间。$1=$1强制替换字段分隔符。此注释中的版本不需要这个选项,赋值就可以了。@jlocke:记住,您可以通过a2p为awk程序提供一个等价的Perl,这个值比其他多余的答案要短得多!如果你有更多这样的任务,我建议你花几个小时学习AWK,它真的会把它们钉牢;我认为BEGIN{OFS=,;FS=;}FNR>1 | | NR==FNR{$1=$1;splitFILENAME,a,;print$0,a[1]}未经测试可以解决这个问题。更妙的是,只需去掉所有标题FNR>1-无需标题行就可以更轻松地自动处理文件。@BeniCherniavsky Paskin:好建议。哇,感谢perl,我担心这将是一个巨大的项目。。。我不确定open