さて、ファイルの最後に 0 を持つ空のレコードがもう 1 つあります。ヘッダーの追加やその他の printf 出力の微調整は、練習問題として残されています。:)
基本的に、ファイル全体を読み取り、レコードに分割し、レコードごとに /g 正規表現を使用してサブ区切り文字を数えます。/g はすべての一致の配列を返すため、@{[]} を使用して配列参照を作成し、スカラー コンテキストでそれを逆参照してカウントを取得します。問題のその特定の部分に対するより洗練された解決策が必要ですが、何でも構いません。パールラインノイズです。;)
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);
これは、少なくとも 1 つの非スペース文字を含むフィールドのみを保持する修正バージョンです。これにより、最後のフィールドが削除されますが、他の空のフィールドも削除されるという結果になります。また、$/ と \Q\E を使用して、いくつかの明示的な関数呼び出しを減らします (ありがとう、アレックス)。そして、前のものと同様に、strict + warnings で動作します。
#!/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);