2 つのテキスト内の数字を 1 行ずつ割り算する
2009-06-09 - 苦悩するだめ日記5に書かれてある問題を解いてみます。 解くための方法はいくつかあると思いますが、paste コマンドを使うと一行野郎で記述することができます。
$ cat total.txt 25 20 0 14 $ cat ok.txt 20 18 0 0 $ paste ok.txt total.txt | nawk '$0=$2?$1*100/$2"\nGYO = "NR:"GYO = "NR' 80 GYO = 1 90 GYO = 2 GYO = 3 0 GYO = 4
awk は paste コマンドとは非常に相性が良いのですが、逆に paste コマンドを使うと簡単なものを awk 単独で行おうとすると難しくなります。
#! /usr/local/bin/nawk -f
# total_ok.awk
# 2 つのテキスト内の数字を 1 行ずつ割り算する
# usage: nawk -f total_ok.awk file1 file2
BEGIN {
total_file = ARGV[1];
ok_file = ARGV[2];
while (getline < total_file > 0) {
total[++nr1] = $0;
}
close(total_file);
while (getline < ok_file > 0) {
ok[++nr2] = $0;
}
close(ok_file);
for (i = 1; i <= nr2; i++) {
if (total[i] == 0) {
print "GYO = " i;
} else {
print ok[i] * 100 / total[i];
print "GYO = " i;
}
}
}
実行してみると以下のような結果が得られます。
$ nawk -f total_ok.awk total.txt ok.txt 80 GYO = 1 90 GYO = 2 GYO = 3 0 GYO = 4
これでは awk らしくなく、全てを配列に格納するため、メモリ効率も悪いので、以下のようなものを作りました。
#! /usr/local/bin/nawk -f
# total_ok_2.awk
# 2 つのテキスト内の数字を 1 行ずつ割り算する
# usage: nawk -f total_ok_2.awk file1 file2
BEGIN {
ok_file = ARGV[1];
total_file = ARGV[2];
}
FILENAME == ok_file {
ok[FNR] = $0;
}
FILENAME == total_file {
if ($0 == 0) {
print "GYO = " FNR;
} else {
print ok[FNR] * 100 / $0;
print "GYO = " FNR;
}
}
前述のものとファイルの指定順序が異なりますが、以下のように実行します。
$ gawk -f total_ok_2.awk ok.txt total.txt 80 GYO = 1 90 GYO = 2 GYO = 3 0 GYO = 4
他にも様々な方法があると思いますので、いろいろ試してみてください。




