BASHとPowerShellのフィルタ処理例をまとめていきます。下記記事たちの続きですので、フィルタそのものの説明、目的、検証環境などの前置きは記事①をご参照ください。
■BASHとPowerShellのフィルタ処理まとめ①
■BASHとPowerShellのフィルタ処理まとめ②
■BASHとPowerShellのフィルタ処理まとめ③
■BASHとPowerShellのフィルタ処理まとめ④
①と②は主に文字列のフィルタ処理についてまとめ、
③は主に行に関するフィルタ処理をまとめました。
④では主に列に関するフィルタ処理をまとめました。
本記事⑤では計算や集計について記載していきます。
テスト用のファイルは以下を使用します。
氏名,氏名(カタカナ),性別,年齢,出身地,血液型,乱数,パスワード
須藤萌花,スドウモエカ,女,66,沖縄県,B,799,903
今田陽向,イマダヒナタ,女,38,徳島県,A,2,584
古川美雪,フルカワミユキ,女,14,神奈川県,O,686,483
海老原瑠美,エビハラルミ,女,14,大分県,A,812,501
沢田義美,サワダヨシミ,女,87,静岡県,B,453,614
金子里歌,カネコリカ,女,77,岡山県,A,311,609
梶田秀之,カジタヒデユキ,男,20,大阪府,A,560,793
諸星英晴,モロボシヒデハル,男,19,新潟県,O,203,133
野上柚,ノガミユズ,女,60,愛知県,O,66,792
佐竹晴久,サタケハルヒサ,男,74,岩手県,A,424,142
ではぽんぽんと紹介していきます。
##【四則演算】
###◆BASHの場合
整数計算はexprを使用します。掛け算(*
)の時だけ\
でエスケープしなければ構文エラーになるので気をつけてください。
[root@centos74 log]# expr 1 + 2
3
[root@centos74 log]# expr 2 - 1
1
[root@centos74 log]# expr 3 \* 3
9
[root@centos74 log]# expr 3 / 3
1
[root@centos74 log]# expr 5 % 3
2
###◆PowerShellの場合
式を入力するだけで結果が返ってきます。ただしPowerShellは型変換があるので暗黙の型変換には気をつけてください。
PS C:\Tools\logs> 1 + 2
3
PS C:\Tools\logs> 2 - 1
1
PS C:\Tools\logs> 3 * 3
9
PS C:\Tools\logs> 3 / 3
1
PS C:\Tools\logs> 5 % 3
2
##【結果を小数点にする】
割り算の結果を小数点にする場合の方法です。
###◆BASHの場合
echoとbcを使用して行います。桁数を制限したい時はscale=桁数
で指定してから計算します。
[root@centos74 log]# echo "5/2" | bc
2
[root@centos74 log]# echo "5/2" | bc -l
2.50000000000000000000
[root@centos74 log]# echo "scale=2; 5/2" | bc
2.50
###◆PowerShellの場合
式を並べれば小数点の計算も通常通りしてくれます。桁数を指定したい場合はフォーマット演算子を使用します。
PS C:\Tools\logs> 5 / 2
2.5
PS C:\Tools\logs> "{0:N4}" -f (5 / 2)
2.5000
##【パーセント値で表示】
###◆BASHの場合
BASHは各コマンドをうまく組み合わせてパーセント値計算するしかありません。
[root@centos74 log]# num=`echo "scale=2; 2/5" | bc`
[root@centos74 log]# num=`echo "$num * 100" | bc`
[root@centos74 log]# echo "$num%"
40.00%
###◆PowerShellの場合
フォーマット演算子で用意されているのでそれを使用します。この時に"{0:Pn}"
のnの値で小数点の桁数表示も指定できます。
PS C:\Tools\logs> "{0:P2}" -f (2 / 5)
40.00%
##【10進数⇔16進数への変換】
###◆BASHの場合
echo+bcの組み合わせで行います。
[root@centos74 log]# echo "obase=16; 4517" | bc
11A5
[root@centos74 log]# echo "ibase=16; 11A5" | bc
4517
###◆PowerShellの場合
フォーマット演算子やToInt32を使用します。
PS C:\Tools\logs> "{0:X}" -f 4517
11A5
PS C:\Tools\logs> [System.Convert]::ToInt32("11A5",16)
4517
##【列の合計値算出】
###◆BASHの場合
BASHで簡単に計算や集計を行う場合はawkを使います。
[root@centos74 log]# cat personal_infomation06.csv | awk -F "," '{sum+=$7} END{print sum;}'
4316
$7というのは7列目のことでここでは乱数列を指しています。-Fで各データの区切り文字(,
)を指定しています。一つ目の{}
内はいわゆるfor文のように内枠の処理を各データに対して繰り返すようになっています。sum+=$7
で7列目の各データを足していく処理を行っています。そして二つ目のEND{print sum}
で合計が完了したsumを表示(print)させています。
###◆PowerShellの場合
PowerShellはMeasure-Objectコマンドレットで行います。
PS C:\Tools\logs> $DATA = Import-Csv .\personal_infomation06.csv
PS C:\Tools\logs> ($DATA.乱数 | Measure-Object -Sum).Sum
4316
いつものパターンですが対象ファイルの各データをオブジェクトに格納しています。その後、Measure-Objectを使用して算出しています。PowerShellはカウント、平均、合計、最小値、最大値の求め方はこの構文ひとつ覚えておけば算出できるようになります。
##【列の平均値の算出】
###◆BASHの場合
[root@centos74 log]# cat personal_infomation06.csv | sed -e'/氏名/d' | awk -F "," '{sum+=$7} END{print sum/NR}'
431.6
awkは組み込み変数があり、それぞれ特定の意味を持った値を格納しており、これを利用することにより柔軟に様々な処理を行えるようになっています。NRは「プログラムが実行開始してからそれまでに入力されたレコードの数」が格納されています。
注意する点としてヘッダー部分(計算対象外のデータ)もNRは数えてしまうので、sedなどであらかじめ削除した後にawkへパイプで渡してください。
[root@centos74 log]# cat personal_infomation06.csv | awk -F "," '{$7} END{print NR}'
11 #先頭の「乱数」もデータとしてカウントしてしまっているので意図した値より1多い。
###◆PowerShellの場合
Measure-Objectの-Averageを使います。構文は合計値算出時と変わりません。
PS C:\Tools\logs> $DATA = import-Csv .\personal_infomation06.csv
PS C:\Tools\logs> ($DATA.乱数 | Measure-Object -Average).Average
431.6
##【列の最大値の算出】
考え方は同じです。
###◆BASHの場合
[root@centos74 log]# cat personal_infomation06.csv | sed -e'/氏名/d' | awk -F "," '{if(max<$7) max=$7} END{print max}'
812
sedしなくてもいいんですが、正確にやる意味も込めて一応しておきます。
###◆PowerShellの場合
-Maximumを使用します。
PS C:\Tools\logs> $DATA = import-Csv .\personal_infomation06.csv
PS C:\Tools\logs> ($DATA.乱数 | Measure-Object -Maximum).Maximum
812
##【列の最小値の算出】
###◆BASHの場合
[root@centos74 log]# cat personal_infomation06.csv | sed -e'/氏名/d' | awk -F "," 'BEGIN{min=9999999}{if(min>$7) min=$7} END{print min}'
2
BASHでの最小値設定は最初にmin(変数)に初期値を当ててあげないとif(min>$7)
の分岐処理時に空白値のminの方が大きいと判断してしまうためNGです。必ず対象列の中のどの数値よりも大きい数値を初期値として設定してください。
###◆PowerShellの場合
-Minimumを使用します。
PS C:\Tools\logs> $DATA = import-Csv .\personal_infomation06.csv
PS C:\Tools\logs> ($DATA.乱数 | Measure-Object -Minimum).Minimum
2
##【列のデータ数をカウント】
###◆BASHの場合
[root@centos74 log]# cat personal_infomation06.csv | awk -F "," '{$7} END{print NR}'
11
###◆PowerShelの場合
-Countを使用します。
PS C:\Tools\logs> $DATA = import-Csv .\personal_infomation06.csv
PS C:\Tools\logs> ($DATA.乱数 | Measure-Object).Count
10
PowerShell側のImport-Csvは先頭行をヘッダーとして読み込んでしまうのでBASHより1少ないです。もしヘッダーも数えたいとのことであればConverFrom-Stringで変数格納してやってみてください。
PS C:\Tools\logs> $DATA = get-Content -Encoding UTF8 .\personal_infomation06.csv | ConvertFrom-String -Delimiter ","
PS C:\Tools\logs> ($DATA.P7 | Measure-Object).Count
11
##【テキストファイルの行数・文字数・単語数カウント】
###◆BASHの場合
BASHはwcを利用してカウントします。
[root@centos74 log]# cat personal_infomation06.csv | wc -l
11
[root@centos74 log]# cat personal_infomation06.csv | wc -m
346
[root@centos74 log]# cat personal_infomation06.csv | wc -w
11
単語は,スペース,タブおよび改行で区切られた文字列の数と区別するためこうなっちゃいます。
###◆PowerShellの場合
Measure-Objectを使用します。
PS C:\Tools\logs> (Get-Content -Encoding UTF8 .\personal_infomation06.csv | Measure-Object -Line).Lines
11
またLengthメソッドでも行数カウントは可能です。
PS C:\Tools\logs> (Get-Content -Encoding UTF8 .\personal_infomation06.csv).Length
11
PS C:\Tools\logs> (Get-Content -Encoding UTF8 .\personal_infomation06.csv | Measure-Object -Character).Characters
335
PS C:\Tools\logs> (Get-Content -Encoding UTF8 .\personal_infomation06.csv | Measure-Object -Word).Words
11
ここで気づいたのですが、BASHとPowerShellの文字数カウントの結果数が異なります。調べてみた結果、1行につき1文字ずつBASHの方が多い(PowerShellが少ない)ようです。行数ごとという観点からおそらく改行コードの分で差が出ているのかなと考えますが、知ってらっしゃる方いたらぜひ教えてください...!!!!
##【⑥に続きます】
⑤が長くなったので一旦⑥に続きます。
⑥は集計について紹介していきます。
ここまで閲覧頂きありがとうございました。
なにか追加情報や指摘事項、「もっといい方法あるよ!」などありましたらコメントへお願いします。