0

我有一个输入文件如下。我需要根据 2,3&5 列将它们分成多个文件。该文件有更多列,但我使用 cut 命令仅获取所需的列。

12,Accounts,India,free,Internal
13,Finance,China,used,Internal
16,Finance,China,free,Internal
12,HR,India,free,External
19,HR,China,used,Internal
33,Finance,Japan,free,Internal
39,Accounts,US,used,External
14,Accounts,Japan,used,External
11,Finance,India,used,External
11,HR,US,used,External
10,HR,India,used,External

输出文件:

Accounts_India_Internal --
12,Accounts,India,free,Internal

Finance_China_Internal --
13,Finance,China,used,Internal
16,Finance,China,free,Internal

HR_India_External --
12,HR,India,free,External
10,HR,India,used,External

HR_China_Internal --
19,HR,China,used,Internal

等等..

请让我知道如何实现这一目标。

截至目前,我正在考虑根据这些列(2、3、5)对文件进行排序,然后在每条记录上运行一个循环并开始创建文件。如果文件不存在,则创建并添加记录。否则打开旧文件并添加记录。

是否可以使用 shell 脚本(bash)来做到这一点?

4

4 回答 4

5

是否可以使用 shell 脚本(bash)来做到这一点?

如果您只是想根据字段 2、3 和 5 拆分文件,您可以使用以下方法快速完成awk

awk -F, '{print >> $2"_"$3"_"$5}' infile.txt 

这会将每一行附加到名称由字段 2、3 和 5 组成的文件中。

例子:

[me@home]$ awk -F, '{print >> $2"_"$3"_"$5}' infile.txt 
[me@home]$ cat Accounts_India_Internal
12,Accounts,India,free,Internal
[me@home]$ cat Finance_China_Internal
13,Finance,China,used,Internal
16,Finance,China,free,Internal

如果您确实想要对输出进行排序,您可以首先通过sort.

sort -k2,3 -k5,5 -t, infile.txt  | awk -F, '{print >> $2"_"$3"_"$5}'

这在将字段 2、3 和 5 上的行传递给awk命令之前对其进行排序。

请注意,我们将附加到文件中,因此如果您重复该命令而不删除输出文件,您最终会在输出文件中得到重复的数据。要解决这个问题,以及包括您在聊天中提到的附加要求(使用第一行作为所有新文件的标题) ,请参阅此解决方案

于 2012-09-20T15:20:50.293 回答
1

我建议你保留一个文件句柄的散列,由它们相应的文件名键入

这个程序演示。输入文件应作为命令行上的参数

use strict;
use warnings;

my %fh;

while (<>) {
  chomp;
  my $filename = join '_', (split /,/)[1,2,4];
  if (not $fh{$filename}) {
    open $fh{$filename}, '>', $filename or die "Unable to open '$filename' for output: $!";
    print "$filename created\n";
  }
  print { $fh{$filename} } $_, "\n";
}

输出

Accounts_India_Internal created
Finance_China_Internal created
HR_India_External created
HR_China_Internal created
Finance_Japan_Internal created
Accounts_US_External created
Accounts_Japan_External created
Finance_India_External created
HR_US_External created
于 2012-09-20T15:27:13.297 回答
0

注意:要使用代码,只需更改<DATA><>使用文件名作为参数。该Data::Dumper印刷品仅用于演示目的,也可以删除。

use strict;
use warnings;
use Data::Dumper;

my %h;
while (<DATA>) {
    chomp;
    my @data = split /,/;
    my $file = join "_", @data[1,2,4];
    push @{$h{$file}}, $_;
}
print Dumper \%h;

__DATA__
12,Accounts,India,free,Internal
13,Finance,China,used,Internal
16,Finance,China,free,Internal
12,HR,India,free,External
19,HR,China,used,Internal
33,Finance,Japan,free,Internal
39,Accounts,US,used,External
14,Accounts,Japan,used,External
11,Finance,India,used,External
11,HR,US,used,External
10,HR,India,used,External

要打印文件,您可以使用如下子例程:

for my $key (keys %h) {
    print_file($key, $h{$key};
}
sub print_file {
    my ($file, $data) = @_;
    open my $fh, ">", $file or die $!;
    print $fh "$_\n" for @$data;
}
于 2012-09-20T15:26:41.277 回答
0

将输入文本保存为 foo,然后:

cat foo | perl -nle '$k = join "_", (split ",", $_)[1,2,4]; $t{$k} = [@{$t{$k}}, $_]; END{for (keys %t){print join "\n", "$_ --", @{$t{$_}}, undef }}' | csplit -sz - '/^$/' {*}
于 2012-09-20T15:30:31.047 回答