04

新年特集 こんなシェルスクリプト、書いちゃダメだ。

12

法林浩之のFITHING TALKS 第8回

14

ユニケージ開発手法 コードレビュー 第10回

19

リナ女のたしなみ 第4回

22

スズラボ通信

28

新連載

30

後藤大地
法林浩之
大内智明
平愛美

すずきひろのぶ
戸倉彩

第13回

戸倉彩の2.5次元の世界

Haskell版Open usp Tukubai完成させるぞ企画

Haskellでやってはいかんのか？ 第10回
上田隆一

34

組織文化を変える汗と涙の物語

アジャイル改善塾

山海一剛、喜多村貴子

36

第9回

「シェル芸に効く」

GNU AWK 処方箋 その4
斉藤博文

40

未来に活きる！現場で使える！

データモデリング 第11回
熊野憲辰

44

IT美女図鑑-近藤佑子

46

Open usp Tukubaiおためし on AWS

50

人間とコンピュータの可能性

52

TechLION再録

60

Tech数独

61

新連載

62

坪和樹
大岩元

第4回

第21回

未来のライフスタイルとテクノロジー

姐のBENTO

吉田松蔭のことば

シェル魔人／編集後記

本誌名称についてvol.21より「USPMAGAZINE」
から「シェルスクリプトマガジン」に、変更となりました。
バックナンバーは「USP MAGAZINE」
としてお求めいただけます。

本誌正式名称は「シェルスクリプトマガジンvol.21」となります。

ちんじゅうちゃん初見月
そのシェルスクリプト、大 丈 夫？

Writer：後藤大地※本記事は、TUKUBAIコマンドを使用しております1. ダメシェルから学べ！
シェルおよびシェルスクリプトはもっとも簡単でもっとも強

大手SIerでは誰が開発しても成果物が同レベルの品質になる力な並列プログラミング向けのソフトウェアです。開発速度のようにミドルウェアやフレームワークを導入し、作業を手続き化

高速さ、マルチコア/メニーコアに対するスケーラビリティのし、時間さえかければ完成するといったレベルまで機械化しま

高さ、動作の明快さ、システムリソースを使い切る潔さなど、
ど

す。
ですので、
できあがるシステムは動くには動くものの、複雑

これだけは必要！
れもとってもハイレベルなソフトウェアです。

で重く、特定のソフトウェアベンダに依存した、
メンテナンスが困難なものになる傾向があります。

こうしてみると万能ツールのように思えますが、シェルやシェ
ルスクリプトにははっきりとした欠点もあります（これはシェル

一方、
シェルはそれを書く人の能力に強く依存するといった匠

スクリプトに限った話ではないのですが、シェルスクリプトはの世界です。中小企業はシェルのアプローチの方が導入しやす

特にこの傾向が強いといえます）。
シェルスクリプトの出来映え

いでしょう。逆に大手SIerも今後はシェルを使う必要性に迫られの良し悪しは、それを書く人のスキルに強く依存するというこるでしょう。従来の開発方式では開発に時間がかかりすぎますとです。

し、利益を出し競争力を維持するにはミドルウェアやフレーム
ワームといった部分の価格の引き下げなどの取り組みも必要

できたものの実行速度に1,000倍以上の差があるなどザラにになるでしょう。従来のミドルウェアやフレームワークから脱却あります。シェルの特性を理解していない開発者が書いたしたいなら、
シェルはそれに適したソフトウェアです。

コードは、遅く、非効率的で、重く、メンテナンスがしんどくて、たまったものではありません。頭がキレる方は複雑なワンライ

では仮に大手SIerがシェルスクリプトベースの開発方式への移ナーを書ける傾向がありますが、それは読みやすさやメンテ

行をはかったとしましょう。
この場合にもっとも大切になるのはナンス性とは真逆のものです。

「教育」
です。少数精鋭のチームを作り、個々人のスキルをひたすらアップグレードする必要があります。

そこで今回の企画です。
どういったシェルスクリプトを書けばよいのか、といった視点ではなく、どういったシェルスクリプトは「ダメなスクリプト」
なのか、
その視点からシェルの技術をお伝えします。
スキルアップに役立てていただければと思います。

42015 January

2. LINE多すぎなダメ
シェルスクリプトの仕事はコマンドを組み合わせることです。

・クッキーおよびセッション管理

コマンドそのものがある程度の機能性を持っていますので、・ログイン認証

シェルスクリプトそのものはとてもサイズが小さくなります。

・POST/GETデータの展開処理

特にエンタープライズシステムのように目的とする処理が明・画面遷移制御

確なものであるほど、シェルスクリプトは短くなります。

・ビジネスロジックの処理

目安は100行から200行くらいです。
このあたりで抑えることができると、メンテナンスがしやすく、処理の流れを簡単に把握できて実に良いスクリプトです。

・入力データの健全性チェック
このケースでは、
まず新しいコマンドをいくつか開発します。作
成するコマンドは単機能にします。1機能1コマンドといった感じです。
どういった名前でどういった単位をコマンドにしてもよ% wc -l KEIRI_SHORI_A001.SH
3024 KEIRI_SHORI_A001.SH%

プロンプト2.1 数千行に達したシェルスクリプトは抜本的に問題があるダメ
逆に、シェルスクリプトの行数が数千行に到達している場合には、いくつかの理由で設計と実装が破綻している可能性があります。その場合には次のような改善を実施すべき時にきていると言えます。
・シェルスクリプトで処理するのではなく、専用のコマンドを開発した方がよいのではないか
・複数のシェルスクリプトに分割できるのではないか
・そもそも実装のやり方を間違っていないか
たとえば、CGIをシェルスクリプトで書いたとしましょう。次の処理をすべて単一のシェルスクリプトに書いたのであれば、いのですが、たとえば上記処理であれば次のようなコマンドを開発することになるでしょう。
・ログイン認証コマンド

login_check・セッション管理コマンド

session_check

・入力データチェックコマンド data_check・POSTデータの展開処理

get_post

・GETデータの展開処理

get_getシェルスクリプトは画面遷移制御を実施するものがCGIのメインとなり、ビジネスロジックの処理は別途シェルスクリプト化してCGI側から呼び出すといった分割になると思います。
このように、実装すべき対象をちゃんと把握、理解し、適切な処理範囲に落とし込むことが大切です。なんでもかんでもひとつのシェルスクリプトに突っ込んでいる場合には、
そもそも対象となるもの（それは業務であったり研究対象であったりさまざま
だと思います）を理解していないことが考えられます。

それはすぐに数千行に到達するでしょう。

5

3. 引数オーバーなダメ
次のシェルスクリプトを見て、一発で「これは嫌な感じがする」

1. data_2015*をパス名展開。一致するすべてのファイル名
またはディレクトリ名へ展開すると思えるようになれば、もはやこの記事の内容は読まなくてもよいでしょう。
このシェルスクリプトは実に危険な香りがしま

2. grepを実行。引数としてkeywordと展開したパス名を渡すす。システム運用を開始してから数年後に発動するタイプのここで注目すべきは、コマンドに指定できる引数には上限があ危ないコードです。

るということです。無制限に引数を渡すことはできません。
シェ

リスト3.1 パス名展開した結果が引数の上限値を超えるダメな

ルスクリプトでは実行速度の高速化などの目的でファイルを多ケース用しますので、data_2015*で展開される名前はシステムの運用が進むにつれてどんどん増えていくでしょう。そうなると、い#!/bin/sh

つの日か、次のような事態が発生します。
grep keyword data_2015*% grep keyword data_2015*
grep: Argument list too long

スクリプトから推測するに、カレントディレクトリに「data_日%付」
といった形式のデータファイルが置かれているのでしょ

プロンプト3.2 忘れた頃にやってくる大問題う。
ここから特定のキーワードに一致する行を抜き出すというだいたい問題というのは忘れた頃にやってくるものですから、処理ですが、「data_2015*」がパス名展開された結果の個数

こうした問題が発生するコードは仕込まないのが鉄則です。将が問題です。

来にわたってロバストに動作するシェルスクリプトを組み上げ

シェルはシェルスクリプトの3行目を処理する段階で次のようることが、緊急出動といったストレスフルな生活から抜け出すな処理を行います。

ための秘訣です。

4. メンテナンス時発火パターンのダメ
シェルでは $$ が自身のプロセス ID に展開されます。動作

ナントカカントカの部分にはいろいろと処理が書いてあるしている間、この値はシステムにおいてユニークな番号とのでしょう。

なりますので、この値を利用して一時ファイルを作るといっ

次のような条件が重なると結構危険です。

たことをよく行います。典型的には /tmp/$$ といったパス

・$tmp が実は使われていないことにメンテナンス中にでの利用です。tmp=/tmp/$$ のように変数を用意して、シェ

気がついた

ルスクリプトの内部で $tmp-out1、$tmp-out2 といったよ・最後に rm のコードがあることに気がついていない

うに一時ファイルとして使います。

一時ファイルを作成せずにパイプでつないだ方がシンプル

これは便利な方法ではあるのですが、時にヒューマンエラーになったり高速になったりする場合など、後からコードをによるとんでもない事故を発生させる原因になることがあ

書き換えることもあります。この場合、$tmp の必要性がります。次のシェルスクリプトはとてもデンジャラスです。

なくなり、3 行目の設定を削除する可能性があります。3

リスト 4.1 メンテナンス時発火パターンのダメ

行目が削除された場合、最後の行の「rm -rf ${tmp}*」は#!/bin/sh

どのように評価されるでしょうか。
$tmp は空文字列に展開されるだけですので、最後の行は

tmp=/tmp/$$「rm -rf *」となります。このシェルスクリプトを実行したプログラムのカレントディレクトリ以下が一気に削除される

ナントカ
command something > $tmp-out
カントカ

関係者の誰かが死にかねない重大なインシデントといえます。
この手のエラーでバックアップファイルが飛んだとか、システムを壊してしまったというのは実際にこれまでに例が

rm -rf ${tmp}*6

わけですので、変更を実施した方やその上司の首が飛ぶか、ありますので、よく気をつけておきたいところです。

2015 January

5. パイプを理解していないダメ
シェルスクリプトの本質的な技術というか、これがあるかルで実行できる内容だからです。化ける必要はなく、そらシェルスクリプトは価値があると言える機能に「パイプ」のまま処理をします。

があります。けれども、実際にこれがどのように動作する

ここで注目すべきは、while はコピーされた別のプロセス

ものかを理解していないと、とんでもない誤ったコードをで実行されている、ということです。プロセスはお互い書いてしまうことがあります。たとえば次のコードを読んにメモリ空間が独立しています。別プロセスで合計値をでみてください。seq 1 10 は echo 1 2 3 4 5 6 7 8 9 10 と同計算したとしても、その結果はもとのシェルプロセスにじような意味になります。while read i で変数 i に 1 から 10はまったく影響を与えません。ですので、合計値が元のまでの値が順次代入され、total=$(($total + $i)) でそれを加シェルに反映されることはなく、初期値として設定した算しているように見えます。最後に echo $total で出力して0 が出力されているわけです。

いますから、標準出力には合計値である 55 が出力されると「思い込んで」しまうところです。

パイプは基本的に並列プログラミングを実施するものだ

リスト 5.1 まったく意味がないシェルスクリプトと考えておいてください。それぞれは独立して動作しま#!/bin/sh

すので、パイプで連結した段階で別空間で動作するようになります。上記の例を動作するように書き換えるとす

total=0
seq 1 10 |while read idototal=$(($total + $i))done
echo $total

しかし、実際にこのコードを実行して出てくる値は 0 です。

れば、次のようにファイルを利用します。
リスト 5.2 プロセスを超えるデータの受け渡しにはファ
イルを使う#!/bin/sh
total=0
seq 1 10 |while read idototal=$(($total + $i))

これはパイプの挙動を理解していないがための誤りです。
「command1 | command2」といった使われ方をした場合、
シェルはまず自分のコピーを 2 つ作成します。この段階でシェルは同時に 3 つ存在することになります。当然、それ

echo $total >> out
done
tail -1 out

ぞれ別のプロセス ID をもった個別のプロセスです。コピー

ただし、このシェルスクリプト自体がそもそもシェルスされたシェルは、ひとつはその後 command1 へ、もう１つ

クリプト的なものではないので、あんまり参考にはしなはその後で command2 へ変身します。この段階で初めて指いでください。処理も遅いですし、これもダメなシェル

定されたコマンドとして機能しようとするわけです。

スクリプトです。

上記シェルスクリプトの場合には「seq | while」ですので、
まずシェルは自分のコピープロセスを 2 つ作成し、1 つはコピーされた後で seq コマンドへ化けます。もうひとつのコピーされたシェルは、そこから化けることなく while の処理
をはじめます。while から done までのコードはすべてシェ

7

6. モニタリング機器
から集計されてくる
データのサンプル

7. シェルの利点まったく使ってなくてダメ

以降では具体的にエンタープライズシステムで活用される用意したモニタデータから、特定の機材の特定の時間帯の、

サンプルデータを扱いながら、ダメなシェルスクリプトを

計測値の平均値を求める場合を考えてみましょう。たとえば見ていきましょう。

機材番号 306 に関して、2015 年 1 月 1 日 12 時台の計測値の平均値を求めてみます。よく使われている手続き型またはオ

ここでは次のようなデータを扱うものとします。1 列目がブ ジ ェ ク ト 指 向 系 の プ ロ グ ラ ミ ン グ 言 語（C、Java、

機材番号（000～999）、2 列目がモニタリングを実施した日

Objective-C、C++、C#、PHP、Python、JavaScript、Perl、時（yyyymmddHHDDMM）、3 列目が計測値（000～999) です。

Visual Basic など）を使ったことがある方なら、次のようなシェ

モニタリングしているのは温度かも知れませんし、電圧やルスクリプトを書くでしょう。

電流かもしれませんし、携帯電話通信網のルータが送ってリスト 7.1 手続き型的な発想で書いたシェルスクリプト

くるデータかもしれませんし、具体的なところはなんでもよいのですが、だいたいこんな感じのデータが集計されてきます。実際にはもっと列数は多くて、数十から数百といったところです。

#!/bin/sh
total=0lines=0
while read id datetime value% head data

do

556 201501011225 001

if [ $datetime -le "201501011259" -a \839 201501011236 923$datetime -ge "201501011200" ]567 201501011228 480

then

651 201501011240 473

if [ $id = "306" ]306 201501011235 765

then

353 201501011208 332

total=$(echo "$total + $value" | bc)

580 201501011258 643

lines=$(($lines + 1))

140 201501011206 751

fi

021 201501011202 602

fi

184 201501011204 679

done < data

% gyo data

echo $(($total / $lines))

1000000%

一見、なんら問題はないように見えます。データを 1 行ずつ

プロンプト 6.1 ナニかのモニタリングデータ 100 万件分

読み込み、まずは日付で処理すべきデータを判定、さらに機材番号で切り分けを実施して、計測値を加算していく。最後

このデータはいわゆるトランザクションに分類されるデーに合計値をデータ数で割り算して平均値を出力する、という

タの、整理をする前の状態です。機材番号ごとに整列されコードです。

ているわけでもなく、日時で整列されているわけでもあり

このコードには実際に問題があるわけではないのですが、こません。

のシェルスクリプトはシェルスクリプトの利点をまったく使い切れてません。とにかく動作が遅いです。プロセッサコアが増えても性能が上がりませんし、典型的なダメシェルスク
リプトと言えます。ともかく、手続き型的な書き方になっていたら、それはシェルスクリプト的ではないと思っておいて
ください。

8

2015 January

8. まったくスケールしないダメ
先ほどの処理をちょっとシェルスクリプトっぽく書いてみま

こちらは複数のコマンドをパイプで接続して高速に動作すしょう。先ほどのような処理はすべて AWK で記述できます。

るようになっています。いくつかの高速化テクニックも取書くとこんな感じです。

り込まれています。箇条書きするとこんな点が注目ポイン

リスト 8.1

トです。

#!/bin/sh

・最初に grep(1) コマンドを使ってデータの絞り込みを
awk 'BEGIN{total=0;lines=0;}

行っている。grep(1) はもっとも高速に動作するコマンド$2<=201501011259&&のひとつで、これを使って最初にデータを絞り込むのは$2>=201501011200&&

高速動作のために定石中の定石$1=="306"{total=total+$3;lines++;}{}
END{printf("%d\n",total/lines)}' data

最初の手続き型っぽい書き方と比べるとこいつはべらぼうに
速く動きますが、残念ながらマルチコア / メニーコアに対してスケールしません。1 コアでも 32 コアでも同じ性能になってしまいます。それはパイプラインを使っていないからです。
複数のプロセスが並列して動作していれば、コアの数が増えれば性能も向上しますが、プロセスが 1 つしかないとスケー
ルのしようがありません。
手続き型のプログラミング言語と比べると多少特殊ですが、AWK を使うとすべて手続き型的な書き方をすることもできます。実際、シェルスクリプトを開いたら全部 AWK だったということもあります。シェルスクリプトに慣れていないた
め、これまで馴染んだ書き方ができる AWK を多用してしまうわけです。しかし、それは単一のプロセスとして実行されるため、性能がスケールしません。シェルを使う場合にはシェルのやり方を覚える必要があります。
マルチコアやメニーコアで性能がスケールするように書き換えると、例えば次のようになります。
リスト 8.2 シェルスクリプトっぽく、かつ、高速に動作する
シェルスクリプト

・self で 2 列目と 3 列目だけを選んで awk(1) へ渡している。こうすることで awk(1) の処理を高速化している・grep、self、awk はパイプで接続され並列に動作している
・$tmp-out に書き出されたデータはすべてキャッシュに載るため、以降はオン・メモリの速度で動作している処理にかかる時間を比べると、その差がはっきりとわかります。
表 8.3 シェルスクリプト実行速度の違い
シェルスクリプト

実行時間

高速さ

手続き型っぽい版

49.48 秒基準

AWK のみ版

0.62 秒

約 80 倍高速

シェルスクリプトっぽい版

0.05 秒

約 1,000 倍高速

手続き型っぽい書き方をした場合と、シェルスクリプトっ
ぽい書き方をした場合とで処理時間が 1,000 倍ほど異なっています。これは重要なことを示唆しています。たとえば
手練れのシェルスクリプトエンジニアが 2 分で処理を終了するバッチ処理を書いたとします。これに対し、シェルス
クリプトに慣れていないエンジニアが手続き型の要領で#!/bin/sh

シェルスクリプトを書いた場合、1,000 倍遅いということ
は 33 時間かかるようなものを作ってしまうということに

tmp=/tmp/$$

なります。
grep "^306" data | self 2 3|

awk '$1<=201501011259&&$1>=201501011200{print "0",$2}'
sm2 1 1 2 2 $tmp-out | self 2> $tmp-out> $tmp-total

夜間バッチなどで実行するとしても 33 時間では 1 日に収まっていませんから、これはまったく使えないシステムということになってしまいます。

echo $(( $(cat $tmp-total) / $(gyo $tmp-out) ))rm -f $tmp-*

99. メモリを使いすぎてダメ
パイプを活用してデータ処理を並列で実行するといった

これをより適切なコードに書き換えると次のようになります。

シェルスクリプト特有の処理に慣れてくると、なんでもか

リスト 9.2 これがシェルスクリプト的良コード

んでもパイプで接続して処理したくなります。そっちの方#!/bin/sh

が高速だからです。しかし一点、ここでコマンドそのものの動作に注意が必要です。コマンドの中にはストリーム的な挙動をしつつ、実は一旦すべてデータをメモリに展開するタイプのものがあるからです。
たとえば、機材番号 306 のデータを、時刻の古いから順に整列して表示させてほしい、といった業務依頼が来たとします。この場合には次のようなコードが思いつくでしょう。
リスト 9.1 メモリ食うし遅いしダメシェルスクリプト#!/bin/sh
sort -k1,2 data | grep "^306" | self 2 3

これはいくつかの点でダメです。まず、sort(1) コマンド

grep "^306" data | self 2 3 | sort -k1,1

sort(1) コマンドの実行は一番後です。最初に可能な限り対象とするデータを絞り込む、これが鉄則です。これはメモリの使用量的な安全策である一方、実行速度にも効いてきます。
この 2 つのシェルスクリプトの実行時間はこれだけ開きがあります。
表 9.3 ちょっと順番を変えるだけでこの速度差
シェルスクリプト

実行時間

高速さ

先に sort(1) している版

3.98 秒基準

後に sort(1) している版

0.05 秒

約 80 倍高速を最初に実行しているところが残念です。sort(1) コマン
ドはその処理の特性上、すべてのデータを読み込んで一端順番を入れ替えるだけで 80 倍の高速化が可能ということにすべてメモリに展開します。そうしないと処理を高速にこなります。このように、シェルスクリプトは書き方次第で大なすことができないからです。

きく性能に差が表れます。実装面だけに絞った場合、シェルということは、処理するデータの量によっては sort(1) コ

スクリプトを使ったシステム開発を成功させる秘訣は、プロ

マンドが動作できずに終了してしまうか、処理が走ったと

グラマ / コーダのレベルでこうした知識や技術を共有できる

してもディスクとメモリとの間でデータのやり取りが無限かどうかにかかっています。

に近い長さで実行されて処理が終わらないという事態が起こるわけです。

10. 関数を使いすぎていてダメ
シェルスクリプトでは関数も利用できますが、関数の利用

・シェルスクリプトはそのシェルが実行するため処理がス

は主に 3 つの理由からあまり推奨されません（もちろんケーケールしない。一定の機能を関数にまとめる必要がある場

スバイケースですが、シェルスクリプトを使った企業シス合、それは別のシェルスクリプトやコマンドとして開発しテムの開発という点ではあまり使いません）。次のような理た方がよい。その方が複数のプロセスとして実行されるた

由があります。

め、マルチコアやメニーコアに対して性能がスケールしやすくなる・シェルの関数は実行される文脈によって動作が変わるというクロージャ的な実装になっており、メンテナンスの段階関数を利用すると、せっかく並列プログラミングが可能なでの書き換えなどで問題を引き起こすことがある

シェルスクリプトの利点が生かせませんし、100 行～200

・シェルスクリプトのように短くすぐに開発できるようなシ行といったコード量ではそもそも関数の利点が得にくいとステムでは、関数に処理を集約するということによるメリッ

言えます。

トが得にくい102015 January

11. 変数を使いすぎてダメ
変数を使用しないプログラミング言語というのはあまりありませんし、シェルにも変数があります。しかし、シェルではあまり変数を使い過ぎない方がよいと言えます。データは綺麗に整理してファイルで保持する。変数はその利用が必要最低限になるようにしておいた方が、何かと便利です。

12. 分岐しまくっていてダメ
シェルスクリプトでは case、if、test、&&、||、などを使って分岐処理を使えますが、これも可能な限り使わない方が良いといえますし、分岐処理の中で分岐処理を実施するといったこともぜひ避けたいところです。シェルスクリプトに落とし込む段階ではデータ処理をパイプで接続したコマンドに流し込むところまで整理しておきます。分岐処理が必要なものについては別途コマンド化するなどして、分岐処理や手続き処理が得意なプログラミング言語を使って実装しておきます。

13. 誰も読めなくてダメ
頭が切れる方は、何重にもなったネスト構造のコマンド置換や eval を活用した処理、コマンド置換や文字列処理などの組み合わせなどで一見するともはやただの記号の羅列にしか見えないコードを書くことがありますが、これもダメです。他の人が読めませんし、往々して将来の自分が理解できないという事態に遭遇することになります。
シェルスクリプトは愚直に、シンプルに、美しく、誰が読んでも理解できる形が理想です。分岐もあまりなく、上から下へ読んでいくだけで内容が理解できる、そういったレベルに維持しておくのがベストと言えます。

14. さらなる高みへ！
ここまで紹介してきたようなことがほぼほぼ頭の中にあるなら、すでにかなり高いレベルのシェルスクリプトエンジ
ニアになっていると言えます。そこからさらにスキルアップをはかるには、ほかのシェルスクリプトエンジニアとの技術交流を持つことをオススメします。
技術は交流することで発展します。ひとりの人間が考えつく発想や実装はたかが知れたところがあります。他人のス
キルや考え方、視点を得ることで、自分が持っていなかった発想方法や実装方法を得ることができますし、新しいア
イディアに結びつくこともあります。
コマンドの使い方やオプションの使い方をひとつとってもそうです。便利な使い方を知っているのと知らないのとでは実装したときの簡潔さや美しさが違ってきます。ダメシェルスクリプトを乗り越えて、さらなるスキルアップを目指しましょう！

11いま私たちは何を学ぶべきか

人間とコンピュータの可能性
第 21 回統計処理と前提条件
written by 慶應義塾大学 名誉教授 大岩 元
ビッグデータのビジネス利用が始まり出した。しかし、ビッグデータを統計処理して意味のある結果を得るためには、「処理対象のデータがどの範囲のものかが特定されていて、その中からランダム・サンプリングされている」という大前提が必要である。これが無視されて、統計処理だけが精緻に実行される例が研究では非常に多い。特に人間に関わる研究において、その傾向が見られる。薬の有効性を保証する治験においても、ランダム・サンプリングが行なわれているとは言い難い。この結果、薬害問題が生じているように私は感じている。
今回は、ランダム・サンプリングについて考えてみたい。

リンゴが赤いか青いかを調べる

るかを考えてみよう。
例題として、「リンゴは赤いか青いか」を調べる問題をコンピュータの普及によって、統計処理が簡単にでき考えよう。果物屋の店頭にあるリンゴから、ランダムにるようになった。従来であれば統計処理を行なうには、数十個ないし数百個のリンゴを選び、白色光を当てて反高度な数学を用いた統計理論を学び、面倒な計算を手

射光の波長の分布を調べれば、赤の波長と緑の波長の作業またはプログラムを書いて行なってきた。しかし統あたりに二つのピークが現われて、リンゴには赤いリンゴ

計パッケージが普及したことにより、利用法を理解しさと青い（緑の）リンゴがあることが確認できる。

えすれば手軽に統計計算ができるようになった。このこと自体は、研究の発展のために喜ばしいことである。

しかし、「リンゴは赤い」ものだと考える人が、店頭から赤いリンゴだけ集めて測定すれば、「リンゴは赤い」とコンピュータが自由に使えなかった60年前には、今のいう結論が得られる。同様に、「リンゴは青い」と考える

ように体に合った既製服を買うことはできなかった。これ

人が青いリンゴを集めて測定すれば、「リンゴは青い」とが、多変量解析がコンピュータのお陰で実用的に使えるいう結論が得られる。

ようになると、日本人の中からランダム・サンプリングでこの二つの結論のうち、どちらか一つだけでは正しい必要とされる人数の人体データを計測することで、日本結果を与えたとは言えない。
「リンゴは赤い」と考えた人

人の体形を少数の体形に分類することが可能となり、既は、自分の結果を正しいと主張し、他の人は、それは間

製服は自分の体形に合ったものを選びさえすれば、スタ違っていると主張するであろう。自分の主張に沿った結イルよく着心地のよいものをどこでも買えるようになった。

論を出したい研究者はしばしばこのような結果を導き出しかし一方で、簡単に利用できることから、統計理論

しがちであるが、その結果は科学的な研究成果とは言えの理解が不十分なまま統計処理を実行する研究が大学ない。

等で行なわれるようになってしまった。特に理論の前提

正しい結果を出すためには、まず「リンゴ」の定義を与となる仮定を吟味せずに、自分に都合のよい結果を得る

え、その定義にあてはまるリンゴの中からランダムに測ためだけに、統計処理が行なわれている場合も見受けら定するリンゴを選んで、測定を行なう必要がある。そのれる。こうした問題を考察する一例として、「リンゴは赤上で結論の妥当性を示す統計処理を行なうことになる。

いか青いか」という思考実験を行なって、何が問題であ対象の定義を与えること、定義を満たすものの中からラ50

2015 Januaryンダムに測定対象を選ぶことが、統計処理を行なうため

本来であれば、例えば新聞の文章を何万文か集め、の重要な前提であり、いかに精緻な統計処理を行っても、その中から課題文に適した文をランダムに選ぶというよう前提が満たされなければ、科学的な結論にはなり得ない。

な手続きをとる必要がある。これは、現在の自然言語処

意味のある統計処理
人間を対象とする研究では、客観的なデータに基づいた議論を行なうのが、物を扱う場合と較べて難しい。こ

理技術を用いれば、十分可能なことである。少なくとも、どのような文章に対して研究結果の主張が行なわれているのかを明らかにすることが必要であろう。
こうした内容の「研究」が、日本を代表する理工系大のため、科学的研究を行なうために統計解析が利用され学で行なわれていたことが、私には信じられない。実験る場合が多い。しかし、統計は大量のデータを対象とすの手続きについては、文句がつけられないように、精密る解析方法であり、これを少数例に対して適用するためな手続きを経て行なわれているが、肝心のデータが解析には、ランダムサンプリングが前提となる。ここで、サンに値するものでなければ、多変量解析を行ってもそれがプリングの対象をしっかり定義し、その中から統計処理

全く意味を持たない。

する対象をランダムに選ぶことが必須となる。

発表された学会の全国大会で、この点を著者に指摘し測定対象を定義することは、客観的な手続きで行なうた所、私の主張を全面的に認めた。主張された内容は、ことではなく、研究者の主観に基づいて決定が行なわれ実験に使用された文に対してしか成立せず、日本語文全ることになる。リンゴの定義は明らかなように見えるが、体に成立するのではないことになると、行なわれた精緻

対象はリンゴに限るか、それとも果物全般ではいけない

な統計解析は全く意味を持たない。論文として全く内容のか、または果樹を対象にするのかは、何を研究するのが無いことになるが、査読済みで公刊された論文を取りかという研究目的と関連して決定しなければならない。

下げることはなかったようである。また、この論文の筆

科学的な研究では、研究命題（Research Question）

頭著者の修士論文であったようだが、それについて議論

を主観的に決めることにこそ、研究の本質がある。これが行なわれた形跡もない。

が決まれば、その後の研究の手続きは客観的に行なえる

STAP 細胞問題で、研究者のモラルが問われているが、その場合も理論の前提に常に注意を払う必要がある。

が、10 年以上前から、大学内ではあやしい研究が行な

2002 年に発表された教育工学の論文に「わかりやす

われてきたのである。現行の学習指導要領では、統計学

い文章表現と文章理解」に関するものがある。この論文者の悲願である統計教育が、やっと本格的に行なわれるでは、「様々な表現をした文章を提示し、その内容に関すようになった。今までは、高校３年の最後に授業をする

る質問を与え、正答率と解答時間によって評価した。そような学習計画になっていたため、大学受験には出題さの結果、内容表現が1つである文は、複数の内容であるれることがなかった。このため、本格的な統計教育は大文より解答時間が有意に短いことを明らかにした。」こと

学レベルでしか行なわれなかったのである。しかし大学が報告されている。結論自体は、常識的に予想されるもでは、複雑な多変量解析もデータを入れれば手軽に行のであって問題ない。しかし、「50 字を超える文は、50

なえる時代が来たために、高度な統計解析ライブラリー

字以下の文に比べ、有意に解答時間が長い」といったこの使い方を教えることが統計の授業の主要部になってしとを統計解析の結果として主張している。この論文の結まったようである。コンピュータの無い論はどの範囲の文章に対して成り立つのであろうか。

時代に統計学を学んだ教授にとっては、

まず、この論文には被験者がどのように選ばれたかの便利な時代になったのであるが、使い記述がない。おそらく著者らの大学の学生であろう。さら方だけ習った学生は、解析の手続きだに問題なのは、課題文の選び方である。種々の実験条件

け学ぶことになってしまう。複雑なことに対して文の長さと漢字の使用率が均一になるようにしが簡単にできる時代は、それを使う側たと記述されており、4つの提示文章が例示してあるだけの教育をどうするかという大きな問題

で , どのような文が使われているかの記述がない。これでをつきつけている

は、実験が行なわれた文の集合に対して結論は主張できのである。

アオそれともアカ？

ても、どの範囲でその結論が有効なのかが明らかでない。

51

ア！
ニケージエンジニ
これであなたもユ

ユニケージ開発手法教育講座「ユニケージ開発手法教育講座」は、ユニケージ開発手法におけるデータ管理の方法や、オリジナルコマンドの使用方法などをハンズオン形式で具体的に学べる講座です。UNIX の基礎からユニケージ開発手法による開発プロジェクトの進め方まで、ユニケージエンジニアとしてのトータルスキルを習得できます。

http://www.usp-lab.com/LECTURE/CGI/LECTURE.CGI
ジ
ユニケー
講座
基礎技術

充実中！
続々と新講座もK - BASIC

ユニケージ基礎編

K - WEB

WEBアプリケーション編

K - BATCH

バッチ処理編（ウェブアプリケーション処理）

K - ARCH

ユニケージアーキテクチャ編

K - SETUP

ユニケージ開発環境セットアップ編

K - UNYO

システム運用・管理編

K - PROJECT

プロジェクトマネジメント・人材育成編

K - SQL

速習：SQL からの移行編

K - STAT

ユニケージにおける統計コマンド編

UNIX 初心者のための講座などもご用意しています。
技術の草原で百獣の王を目指す
エンジニアたちの新感覚トークライブ！

http://techlion.jp/

上記のサービス内容は 2014 年 12 月現在のものです。最新の情報はホームページにてご確認ください。

ISBN 9-784-904807-15-6
C3455 ￥500

USP 研究所
定価（本体 500 円＋税）