「社員名簿」のダミーデータをシェル(とFaker)で作る宣伝。日経LinuxにてLinuxの基礎?を紹介する漫画「シス管系女子」を連載させていただいています。2019このエントリはQiitaとのクロスポストです。シェル芸アドベントカレンダー2019に空きがあったので、最近やったシェルの話で参加させていただきます。自分は日経Linux誌でシス管系女子というシェルの解説記事(マンガ)を連載させていただいてます。その2020年1月号掲載分の回において、「劇中の架空の会社で、アダムズ方式を使って各部署から代表者を何名かずつランダム且つ公平な感じで選ぶシェルスクリプトを作る」という話をやっています。アダムズ方式では、前の計算の結果を使って次の計算を行うというステップが何度か出てきます。今までは「1画面分だけの画面出力」が必要なケースが多かったので都度てきとうにその場の気分で偽の画面をデッチ上げていたものの、こう複雑な話になってくると、それぞれの画面間で数字に矛盾が無いようデッチ上げるのはなかなか大変です。実際にそれっぽい「社員名簿」のダミーデータのCSVを作って、その処理結果をそのまま使うことにしました。いう場面でのダミーデータの作り方はいろいろあると思いますが、描いているのがシェルの解説なので、シェルでやってみました。いうのがこの記事の内容です。用意するダミーデータの形式は「社員番号,氏名,勤務地(拠点),部署」の列を持つCSVという事にします。具体的には以下のような感じです。各フィールドは完全ランダムではなく、以下のような条件を満たす感じにしたいという思惑があります。社員番号は連番にしたい。退職や転職などがあったという想定で、社員番号は適度に不連続にしたい。「特定の時期に退職者が集中している」みたいな事までは考えないことにする。最後の方の数十件くらいは、入って日が浅い人達という事で退職者無しで社員番号が連続するようにしたい(主人公のみんとちゃんもそのあたりに含めたいので)。部署・拠点には偏りを持たせたい。単純に部署をランダムに割り振ると「えっシステム部が数百人規模!?」「本社と支社が同規模ってあり得るの?」みたいな事になってしまって不自然なので。「新部署創設で特定の時期に特定の部署の人が集中している」みたいな事までは考えないことにする。全体の行数は劇中舞台の架空の会社の全従業員数ということになります。劇中では、全国に何カ所か拠点があるかなり大きなBtoCの会社っぽい描き方をしているので、そんな感じの会社を探して組織概要を見てみたら1000人前後とありました。これを参考にしつつ、キリのいい数字よりは半端な数字の方がそれっぽいかと思って1127人と決めました。Directoryとかで認証基盤を組んでユーザーの管理もそこでやるのが当たり前なのでは?というツッコミもあろうと思いますが、なにぶん連載のテーマがシェルなので、「実はそういう技術がまだ発展していないパラレル時空だった」みたいな想像で補って頂けましたら幸いです。それか、たまたまCSVでエクスポートした物があったのでそれを使ったという話でもいいです。)ステップ1:社員番号と名前だけの一覧を作る退職や転職などがあったという想定で、社員番号は適度に不連続にしたい。最後の方の数十件くらいは、入って日が浅い人達という事で退職者無しで社員番号が連続するようにしたい(主人公のみんとちゃんもそのあたりに含めたいので)。この条件に合うデータにしたいので、多めに作って必要な人数分をランダムに抽出することにしました。退職者が多いとブラック企業っぽくなってしまうかなと思ったのですが、程度が分からなかったので、「退職者」まで含めた人数は無根拠でてきとうに1605件と決めました。(普通どれくらいの頻度で人が入って辞めていくのか分からなかったのですが、一般的基準に照らし合わせて離職者多すぎなのであれば、分社化したとかそういう風に想像で補って貰えれば幸いです......)日本人ぽい人名をランダムに自動生成するツールというと、自分はRubyのgemでFaker(使い方)という物があると以前に聞いた事があります。人名部分だけはそれを使って簡単なスクリプトで生成してみました。行を除いた残りの行」を出力する。入力のカンマ区切りの1列目を数値と見なしてソートする。優斗...こんな要領の1127人の「現役社員」の一覧ができます。拠点があって東京本社が一番人数が多い(人数比はとりあえず5:2:1:1と想定)ということにしたいので、数に偏りを持たせた拠点一覧を用意します。少ないので、自分はvimでの手書きコピペで作りました。9行しかありませんが、実際にはこれを繰り返し使うので、1127人分に拡大してもそれぞれ同じ割合になります。同様にして、人数に偏りを持たせた部署一覧を用意します。話の都合上多めに部署を用意したいので、聞いた事のある部署名を12個ほど列挙してみました。各部署の人数は、実際の大会社が実際どんな感じなのか自分は知らないので、想像でてきとうに決めました。17%件数が多くなるので、さっきの拠点一覧と同じ要領で手書きで用意するのはちょっと大変そうです。使って半自動生成します。......__EOF__とするのが「正しい」のですが、データが後から出てくる形式は自分は読みにくく感じるため、先にヒアドキュメントを書く書き方を好んでいます。すると、指定件数より少ない元データからでも、必要な件数分の出力を得られます。divisions-shuffled.csvそれを先の社員番号と名前だけのCSVに列として付け足せば、名簿っぽいダミーデータのできあがりです。件数(--head-count=件数)オプションを併用すると、「与えたデータの各行と同じ登場割合で指定件数の出力をランダムに得る」のではなく、「与えた元データをシャッフルして出力する、という処理を、結果が指定件数に達するまで繰り返す」という動作になります。そのため、結果の先頭の方にばかり「東京」がやたら出てくるみたいな偏りは発生せず(※ランダムに決めるというのは「次の結果がどうなるか予想できない度合いが高い」という事なので、「必ず満遍なく登場する」という予想しやすい結果になる保証は無く、結果の部分部分を見ると偏った感じになる事があります)、拠点と部署は全体で満遍なく登場し、充分に件数が多ければ、各拠点におおむね全部署の人がいるという結果になります(※全体の件数が少ないと、特定の部署の人がいない拠点が出てきやすくなります)。した結果の件数(=その拠点に一人でも人員がいる部署の数)を見ると確かめられます。-l12「開発の人員を集めた拠点」とか「製造の部門を集めた拠点」とかを想定したい場合、データの作り方をまた工夫する必要があります。架空の会社の内情を想像し始めるときりが無いので、今回はそこまでは行わないことにしました。ステップ3:特定の登場人物に差し替える以上でダミーデータのCSVができたわけですが、劇中には既に何人か所属が明らかになっている人達がいます。推定される入社時期から社員番号をてきとうに決めて、こんな風にCSVを用意してみました。みんと,東京,システム部まず、先のダミーのCSVから社員番号がこれらと一致する行を取り除きます。オプションと組み合わせると「与えた除外リストに該当しない物だけ出力する」フィルターとして機能します。特別な人物のCSVの社員番号の列だけを取り出して除外リストにすれば、「社員番号がこれらの人物に一致しない人物だけのCSV」を得られます。members-isolated.csvそうしたら、それと特別な人物のCSVを連結して、再び社員番号順でソートし直します。members.csvこれで、「劇中描写にそれなりに則ったダミーの社員名簿」のできあがりです。書くと、そのコマンド列の実行結果の出力を保存したファイルを指定したのと同じように扱われるという、bashの便利な機能)を使いまくってここまでの話をワンライナーにまとめた物を示してお茶を濁しておく事にします。まとめシェルのコマンドとFakerの組み合わせでダミーデータのCSVを作る例をご紹介しました。Fakerは完全にランダムなダミーデータを作るのに便利なのですが、多少偏りのあるダミーデータを用意しようと思うと工夫が必要です。Rubyでももちろんこの記事に書いたような事はできますが、自由度が非常に高くて色々なやり方が考えられるので、「どこまでこだわるか」の見切りをつけるのが難しくて自分は却って混乱する感じがありました(実際、収拾が付かなくなって途中で放り投げてしまいました)。その点、シェルだとメジャーなコマンド群で簡単にできる事には限りがあり「簡単にできるレベルにとどめよう」という圧が自然とかかるので、入れ込みすぎないで済むというメリットがあるんじゃないかなという気がします。この記事では各段階を迷い無く進めていますが、実際にやった時には、社員番号をランダムに抽出する部分までRubyでやってみたり、先に1605件の部署名込みのCSVを用意してから必要な件数を抽出してみたりと、あれこれ試行錯誤してどうにか希望するアウトプットを得られたという状況でした。この記事の内容は、それを後から振り返って「あっ、ここもっとこういう風に効率よくできたやん」と気付いた所をちまちま最適化した結果の、言うなれば「よそ行きのコマンド列」となっています。1つの事をやるにも解法が色々あり、期待する結果を得られていさえすればそのいずれも正解なのがシェルなので、シェルにまだ自信が無い方々は達人達の極まったシェル芸を見て萎縮してしまわず、自分なりのアプローチでスクラッチでコマンド列を組み立てる練習を重ねてみて下さい。2020年1月号掲載分の回の劇中データには拠点の情報がありません。実は、拠点の情報は日経xTECHで展開中の「シス管系女子」過去回よりぬき+新作Web連載の最後の1話で使う予定で改めて付け加えた物なのでした(どんな使い方をするかは本編を見てのお楽しみ)。スケジュール的に制作が〆切デッドラインに間に合うかどうかギリギリなので、もし最後の1話が過去回の再掲になっていたら「ああ、間に合わなかったんだな......」と笑ってやって頂ければ幸いです。atの末尾に2020年11月30日時点の日本の首相のファミリーネーム(ローマ字で回答)を繋げて下さい。「noda」なら、「2019-12-17_generate-dummy-csv-with-shellcommands.trackbacknoda」です。これは機械的なトラックバックスパムを防止するための措置です。