App-colsummary

 view release on metacpan or  search on metacpan

colsummary  view on Meta::CPAN

#!/usr/bin/perl

#  colsummary : TSVまたはCSVファイルの各列の値の様子を表示する。とても便利。
#   2015/05/11 - 2016/07/05 , 2018-03-28 . Shimono Toshiyuki 
#   2019/10/24, 2021/06/08, 2021/06/11 さらに大幅に書き替え 

use 5.014 ; 
use strict ; 
use warnings ; # also confirmed on 5.011 5.014 5.018  
use autodie qw [ open ] ; 
use Encode qw[ decode_utf8 encode_utf8 ] ; 
use FindBin qw [ $Script ] ; 
use Getopt::Std ; getopts 'R:c:g:i:jm:r:su:v:z=!@:#:0:2:' => \my %o ;
use List::Util qw/max min maxstr minstr/ ; 
use POSIX qw/strtod/ ; # # 平均値の計算に用いる str to double.
use Scalar::Util qw/looks_like_number/;
use Term::ANSIColor qw/:constants color/ ; $Term::ANSIColor::AUTORESET = 1 ; 
use Time::HiRes qw [ gettimeofday tv_interval ] ; my ${ dt_start } = [ gettimeofday ] ; 

my $sdt = sprintf '%04d-%02d-%02d %02d:%02d:%02d', do{my @t= @{[localtime]}[5,4,3,2,1,0]; $t[0]+=1900; $t[1]++; @t } ; 
eval "use PerlIO::gzip;1" or die "PerlIO::gzip cannot be loaded, so -z does not work. ($Script, $sdt)\n" if $o{z} ; 

sub AlignOut ( @ ) ; # 出力 ; eachFileでもColstatでも使う。
sub ColStat ( $$ ) ; # $colvals->[列番] と 列名を 渡す。そして、その中身が表示される。; eachFileでもColstatでも使う。
sub d3 ($) { $_[0] =~ s/(?<=\d)(?=(\d\d\d)+($|\D))/,/gr } ; # 数を3桁区切りに変換する。
sub eachFile ( $ ) ; 
  # 以下3個はeachFileから呼ばれる。
  sub colnames( $ ) ; # -=の時に先頭行の情報を取り出す
  sub filePinfo ; # ファイル毎の2次情報(一行サマリ)
  sub ColFreq ( $$ ) ; # 第1変数はファイルハンドル 第2変数は参照 ;  各列の値の分布を取り出す

## 全体で使う変数
my $optu0 = exists $o{u} && $o{u} eq 0 ; 
* decode = * decode_utf8 ; 
* decode = sub ( $ ) { $_[0] } if $optu0 ; 
#* decode = (! $optu0) ? * decode_utf8 : sub ($){ $_[0] } ; #* encode = $o{u} ? * encode_utf8 : sub ($){ $_[0] } ; 
my $optR0 = defined $o{R} && $o{R} eq 0 ;
* R0proc = $optR0 ? sub {} : sub { s/\r$// } ;  # -R0 が指定された時の処理
binmode *STDOUT , ':utf8' unless $optu0 ; # これだけ全体で使う変数とは言いがたいかもしれないが、オプションの処理はこの節の前半にあるので。
$| = 1 if $o{'!'} ;
$o{g} //= 6 ; # if ( ! defined $o{g} ) ; # 取り出す数
$o{r} //= "~" ; # 範囲を表す記号(出力で使う)
$o{c} //= '|'  ; # 範囲を示す表示を複数繋げる記号(出力で使う)
$o{'#'} = decode ( $o{'#'} ) if defined $o{'#'} ; # 除外する正規表現
push @ARGV , '-' unless @ARGV ; # 標準入力の追加
my $isep = $o{i} // "\t" ;  # 入力の区切り文字 $o{','} = do { $o{','} //= "\t" ; eval qq[qq[$o{','}]] } ;
my $sec = $o{'@'} // 15 ; # 何秒ごとにレポートを表示させるか
my $nc = 0 ; # 計数対象としなかったセルの数をカウント。
my $rl ; # 各ファイルの読んだ行数を格納。
my %fOut = (
j => [map{UNDERLINE decode($_)}map{eval"\"$_\""}qw[列番 異なる値 数値化平均 列名 値の範囲 最頻値 頻度(重複)], q[], '桁数'],
e =>  [ map {UNDERLINE $_ } qw[ cpos diff ave. name range frequent frequency(multi) ] , "",  "digits" ] ) ; 

my $col = undef ; # 0オリジンのカラム番号 ## sub ColFreq 内で使う。
* negcell = defined $o{'#'} ? sub { if (m/$o{'#'}/ ) { $col ++ ; $nc ++ ; goto EACH_CELL } }  : sub {} ; # o{'0'} をやめた


## シグナルに対する設定
my ${ INT1 } = sub {
  &{ $SIG{ALRM} } ;
  print STDERR BRIGHT_RED 
   'Do you want to get the halfway result? Then type Ctrl + C again within 2 seconds. '. "\n" .
   'Really want to Quit? Then press Ctrl + "\" or Ctrl + Yen-Mark. (Ctrl+Z may be what you want.) ' . RESET "\n" ;
  $SIG{INT} = sub { select *STDERR ; & ColStat ; select *STDOUT ; return } ; 
  sleep 2 ; 



( run in 2.068 seconds using v1.01-cache-2.11-cpan-39bf76dae61 )