我有一个输入文件如下。我需要根据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)执行此操作?
答案 0 :(得分: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
命令之前对其进行排序。
请注意我们附加到文件,因此如果重复命令而不删除输出文件,则最终会在输出文件中出现重复数据。要解决此问题,并在the chat中提及您的附加要求(使用第一行作为所有新文件的标题),请参阅this solution。
答案 1 :(得分: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
答案 2 :(得分: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;
}
答案 3 :(得分: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 - '/^$/' {*}