好吧,文件末尾还有一个空记录,它有 0。所以,这里有一个脚本来做你想做的事。添加标题和以其他方式调整 printf 输出留给您作为练习。:)
基本上,读入整个文件,将其拆分为记录,对于每条记录,使用 /g 正则表达式来计算子分隔符。由于 /g 返回一个包含所有匹配项的数组,请使用 @{[]} 创建一个数组引用,然后在标量上下文中取消引用它以获取计数。对于问题的特定部分,必须有一个更优雅的解决方案,但无论如何;这是 perl 线路噪音。;)
user@host[/home/user]
$ ./test.pl ',|' '^%!' test.in
3 1
2 1
1 2
0 3
user@host[/home/user]
$ cat test.in
jdk,|ljn^%!dk,|sn,|fgc^%!
ydfsvuyx^%!67ds5,|bvujhy,|s6d75
djh,|sudh^%!nhjf,|^%!fdiu^%!
user@host[/home/user]
$ cat test.pl
#!/usr/bin/perl
my( $subdelim, $delim, $in,) = @ARGV;
$delim = quotemeta $delim;
$subdelim = quotemeta $subdelim;
my %counts;
open(F, $in) or die qq{Failed opening $in: $?\n};
foreach( split(/$delim/, join(q{}, <F>)) ){
$counts{ scalar(@{[m/.*?($subdelim)/g]}) }++;
}
printf( qq{%i% 4i\n}, $_, $counts{$_} ) foreach (sort {$b<=>$a} keys %counts);
这是一个修改后的版本,它只保留至少包含一个非空格字符的字段。这会删除最后一个字段,但也会导致删除任何其他空字段。它还使用 $/ 和 \Q\E 来减少几个显式函数调用(感谢 Alex)。而且,和前一个一样,它适用于严格的 + 警告;
#!/usr/bin/perl
my( $subdelim, $delim, $in ) = @ARGV;
local $/=$delim;
my %counts;
open(F, $in) or die qq{Failed opening $in: $?\n};
foreach ( grep(/\S/, <F>) ){
$counts{ scalar(@{[m/.*?(\Q$subdelim\E)/g]}) }++;
}
printf( qq{%i% 4i\n}, $_, $counts{$_} ) foreach (sort {$b<=>$a} keys %counts);
如果您真的只想无条件地删除最后一条记录,我偏爱使用 pop:
#!/usr/bin/perl
my( $subdelim, $delim, $in ) = @ARGV;
local $/=$delim;
my %counts;
open(F, $in) or die qq{Failed opening $in: $?\n};
my @lines = <F>;
pop @lines;
$counts{ scalar(@{[m/.*?(\Q$subdelim\E)/g]}) }++ foreach (@lines);
printf( qq{%i% 4i\n}, $_, $counts{$_} ) foreach (sort {$b<=>$a} keys %counts);