献本レビュー:「Windows/Mac/UNIXすべてで20年動くプログラムはどう書くべきか」

#posixismadvent この記事はPOSIX原理主義Advent Calendar4日目だ。

2016-11-10に発売された,POSIX原理主義の実践に必要なテクニックが詰まった書籍「Windows/Mac/UNIXすべてで20年動くプログラムはどう書くべきか」を献本いただいたので,僕の人生初の献本レビューを行う。

Windows/Mac/UNIXすべてで20年動くプログラムはどう書くべきか

献本の経緯

一般的に,献本は著名人・有名人に書評を書いてもらい,書籍の宣伝を目的としてなされるのだと認識している。普通に考えると,僕は別に有名人でもなくただの一般人なので,献本を受けるには値しない。では,なぜただの一般人が献本を受けられたのか?これには,前著「すべてのUNIXで20年動くプログラムはどう書くべきか」に対して僕が行った2個の行動が原因しているのだと思う。

  1. 前著で気になった箇所の指摘
  2. 前著の正規表現の間違いの指摘

なお,僕は読んだ書籍を基本的にブクログとAmazonで感想を記録している。前著の感想は以下で掲載している。

『すべてのUNIXで20年動くプログラムはどう書くべきか デプロイ・保守に苦しむエンジニア達へ贈る[シェルスクリプトレシピ集]』のレビュー 松浦智之 (bkskさん) – ブクログ

前著で気になった箇所の指摘

まず,3月に行われた発表でPOSIX原理主義について興味を持った。そして,発表で紹介されていたPOSIX原理主義について書かれた書籍「すべての UNIXで20年動くプログラムはどう書くべきか」にも興味を持ち,2016-05-07に購入して読んでいた。

すべての UNIXで20年動くプログラムはどう書くべきか

この書籍について疑問に思うところがいくつかあった。ちょうど,書籍のp. 12におかしな所があれば「こっそりツッコミなどをお寄せいただきたい。」と,メールアドレスが掲載されていたので,メールで指摘した。これが始まりだった。2016年9月の話だった。本自体は6月頃に一度読み終わっていたのだが,感想を書いたり,質問しようかなと思っていたら遅くなってしまった。

質問・指摘内容は以下7点だった。

  1. POSIX規格以外の参考文献の不足の指摘
  2. IFS環境変数の挙動
  3. 括弧の名称
  4. sortコマンドと関連して,revコマンドについて
  5. whichコマンドの代替方法
  6. 同じ文字が連続した文字の作成方法
  7. その他要望

著者の許可を頂いたので,そのときのメールでのやりとりの一部を以下に掲載する。

送信日時:2016-09-03T02:46+09:00

妹尾といいます。

書籍「すべてのUNIXで20年動くプログラムはどう書くべきか」を読み気になった箇所があったので,コメントさせていただきます。気に入らないところは無視してください。

なお,返信をいただけるなら,ブログでの公開の可否も教えてください。

序章,p. 9
POSIXの規格以外にも参考になるような書籍や文献があれば具体的な名前をあげていただけるとありがたかった。

1-1 環境変数などの初期化,p. 14
IFSの初期化は単にunset IFSでよいのではないか?POSIXの規格をみると,IFSはセットされていなければ,スペース,タブ,改行とみなされると書かれている。

If IFS is not set, it shall behave as normal for an unset variable, except that field splitting by the shell and line splitting by the read command shall be performed as if the value of IFS is <space> <tab> <newline>; see Field Splitting.

Implementations may ignore the value of IFS in the environment, or the absence of IFS from the environment, at the time the shell is invoked, in which case the shell shall set IFS to <space> <tab> <newline> when it is invoked.
http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_05_03

1-10 local修飾子,p. 21
「小括弧で囲ってサブシェルを作れば,」とあるが,括弧の呼び方が気になる。小・中・大という括弧の呼び方は,学問分野や国・人によって解釈が異なる。見 た目に基づいた呼び名(丸括弧(),山括弧<>,波括弧{},角括弧[])にしたほうがわかりやすくて誤解がないのでとよいと思った。

3-18 sortコマンド,p. 48
sortコマンドと関連して,文字列を反転するPOSIX非準拠のreverseコマンドやそのPOSIXでの実装方法についても記述があればよかった。

3-23 whichコマンド,p. 50
whichコマンドはcommand -vで代替がきく(Qiitaで指摘済み)
http://qiita.com/richmikan@github/items/bd4b21cf1fe503ab2e5c?utm_campaign=email&utm_content=link&utm_medium=email&utm_source=public_mention#comment-026939147972093e169c

COLUMN 同じ文字が連続した文字を作る,p. 104
printfとseqを組み合わせた以下のワンライナーのほうが,簡単で文字でも単語でも対応できるので汎用性が高い(ただし,%.0sはPOSIX非準拠かもしれない)。
printf “文字%.0s” $(seq 回数)

その他
関数の書き方について,解説が少なかったので,もっとあればよかった。位置パラメーターの意味や注意点など。最後にreturn 0を書くべきかなど。

以上です。
送信日時:2016-09-03T11:19+09:00
妹尾さま

著者の松浦と申します。

購読、そして貴重なご意見ありがとうございます。

ブログではぜひ言及してください。
双方向の意見交換がドキュメントをよりよくしていくと思っています。

また、よろしければお礼も兼ねまして「すべての〜」の書籍の後に独自改訂した同人誌版をお送りします。
「すべての〜」は改訂を続けてきた同人誌版の一時期からforkされたもので、
同人誌版はこの夏も改訂版を出しました。

以下に、個別の返答を記します。
ありがとうございました。今後ともよろしくお願いいたします。

> 序章,p. 9
その後、独自改訂をした同人誌版ではいろいろ紹介しています。
書籍 — 入門UNIXシェルプログラミング
書籍 — UNIXという考え方
Web — シェルスクリプト入門 http://www.k4.dion.ne.jp/~mms/unix/shellscript/
Web — Effective AWK Programming
http://www.kt.rim.or.jp/~kbk/gawk-30/gawk_toc.html
Web — UNIXの部屋 http://www.kt.rim.or.jp/~kbk/gawk-30/gawk_toc.html
Web — 会津大学UNIXウィキ http://technique.sonots.com/

> 1-1 環境変数などの初期化,p. 14
過去に、
IFSを参照してきてIFSが未定義ならIFS=”相当の動きをしているっぽい
プログラムに出会ったことがあり(忘れてしまった)、
そういう間違った解釈のプログラムでも正しく動くようにという配慮です。
確かに、IFSがデフォルト定義されているシェルは多かったです。

> 1-10 local修飾子,p. 21
今後発行する機会(同人誌版の改訂等)には是非取り入れます。ありがとうございました。

> 3-18 sortコマンド,p. 48
手近なUNIX系OSをいくつか見たり、Webで軽く調べたりしましたが
reverseコマンドがわかりませんでした。もしかして rev コマンド、
あるいは sort –reverseオプションのことですか?

> 3-23 whichコマンド,p. 50
この後、Qiitaの編集リクエストにも対応します。
もちろん今後改訂する機会(同人誌版の改訂等)でもご指摘に基づきなおします。ありがとうございました。

> COLUMN 同じ文字が連続した文字を作る,p. 104
残念ながらseqコマンドがPOSIXにないのでPOSIX原理主義からは外れてしまいます。
seqはいろいろ便利コマンドなんですけどね。

> その他 ― 関数の書き方
どのあたりを読んでいてそのように感じましたか?
そのあたりの意見を伺いながら、どこに加筆すべきか検討したいです。
送信日時:2016-09-03T13:00+09:00
妹尾です。
早速のご回答ありがとうございました。

> また、よろしければお礼も兼ねまして「すべての〜」の書籍の後に独自改訂した同人誌版をお送りします。
とてもありがたいです(個人的には電子版だとなお嬉しいです)。

>> 序章,p. 9
>その後、独自改訂をした同人誌版ではいろいろ紹介しています。
ありがとうございます。参考にさせていただきます。

>> 1-1 環境変数などの初期化,p. 14
>過去に、
>IFSを参照してきてIFSが未定義ならIFS=”相当の動きをしているっぽい
>プログラムに出会ったことがあり(忘れてしまった)、
>そういう間違った解釈のプログラムでも正しく動くようにという配慮です。
>確かに、IFSがデフォルト定義されているシェルは多かったです。

了解しました。
特に何もコメントがなかったので,一言その旨を書いておけば,完璧かもしれません。


>> 3-18 sortコマンド,p. 48
>手近なUNIX系OSをいくつか見たり、Webで軽く調べたりしましたが
>reverseコマンドがわかりませんでした。もしかして rev コマンド、
>あるいは sort –reverseオプションのことですか?

すみません。記憶が曖昧なままでした。revコマンドのことです。
文字列を逆から取得したいときがあって,文字列処理として逆にするというのは比較的メジャーな処理かなと思いまして。
revコマンドを使わないとけっこうやっかいだなと思ったので,解説されていたら自分は参考になっただろうと思いました。その程度です。


>> 3-23 whichコマンド,p. 50
>この後、Qiitaの編集リクエストにも対応します。
編集リクエストは修正忘れと思われる`type`という単語を`command`に直しただけなので大したものではありませんけどね…


>> COLUMN 同じ文字が連続した文字を作る,p. 104
>残念ながらseqコマンドがPOSIXにないのでPOSIX原理主義からは外れてしまいます。
>seqはいろいろ便利コマンドなんですけどね。

そうでしたか。すみません。確認不足でした。


>> その他 ― 関数の書き方
>どのあたりを読んでいてそのように感じましたか?
>そのあたりの意見を伺いながら、どこに加筆すべきか検討したいです。

例えば,[7-8あなたはいくつ問題点を見つけられるか]!?やp. 51の[3-23 whichコマンド]などでしょうか。いくつか自作関数が登場してきており,そのときの書き方が少し気になりました。よい書き方の指南があるなら参考にしたいと思いました。
関数というよりは,スクリプト本体の書き方に通じるかもしれません。例えば,以下のような項目が解説されていると嬉しかったです。

・引数のチェックをするときは,どういうことを考慮する必要があるか。
・readonlyを使うタイミング。
・関数の実行結果の受け取り方(関数の最後でechoで出力して,A=$(関数)で変数に代入させるとか)
・変数のスコープ(cat a | while readなどパイプで渡した時など,localが使えないなら,unsetで解除したりとか)
・変数や引数を二重引用符や一重引用符で囲むべき箇所(a=$(echo a b c)など,”で囲まなくてもよい場面がある。)
・関数やコマンドに引数を渡す方法(環境変数,引数,リダイレクトなど)の使い分け
・オプションの処理
・ルート権限([ $(id -u) = 0 ]),ユーザー名(id -nu,logname),ホスト名(uname -n),グループの取得・判別
・関数に関数やコマンドを渡す方法(ベンチマークの測り方)


その他,個人的にはPOSIX原理主義でスクリプトを書くときの文法についてもう少し詳しく(体系だてて)書かれているとよかったです。冒頭数十ページにわたり,正規表現など基本事項が書いてあり,参考になりましたが,断片的な印象がして物足りなかったです。

・例えば,正規表現と少し似ているglobの処理。POSIXではglobの否定では^は未定義で,!しか定義されていないことや,.で始まる隠しファイルの処理など。
・bashなどで比較的広く使われているコマンド・文法とそれをPOSIXに準拠させる方法・代替手段(例:function,source,seq)。
・リダイレクトの書き方(前後に空白を挟まない理由,while readで一度に2個以上の変数を読み込む方法)など。
・POSIXのシェル変数の文法の活用(未定義変数の代入(: ${VAR:=var})など)
・testコマンドの書き方(変数に特定文字が含まれていることの判別([ -z “${VAR##*var*}” ]),caseでもできるが,少し込み入った条件分岐をさせたいときにtestで判定したい時があるので)
・POSIXで前提として利用してよい環境変数・シェル変数の一覧・解説。

POSIX原理主義の範囲を超え,ただのシェルスクリプトの解説に収めるべき箇所もあるかもしれませんので,おかしなところは適当に読み流してください。

POSIX原理主義はよい考えだと思いますので,今後の改訂や新書の出版を期待しています。

自分の勘違いもあり,質問したことで自分の勉強にもなった。

前著の正規表現の間違いの指摘

9月にメールで指摘した後,しばらくして個人的に正規表現の勉強が必要だと思った。それで,POSIXの正規表現の規格と前著の「第2章 どの環境でも使えるシェルスクリプ トを書く正規表現編」のページの両方を参考にして勉強していた。POSIX規格と照らし合わせていくと,前著の記載内容に誤りがあることに気づいた。それを2016-10-23にTwitterで指摘した。

ちなみに,そのp. 26で僕が言及した箇所は以下の正規表現の角括弧記法内のメタ文字を説明している表だ。

すべてのUNIXで20年動くプログラムはどう書くべきか」p. 26の指摘箇所

この件について,ツイッター上で質疑応答が行われ納得してもらえた。一連の質疑応答は上記のツイートのリンクを開けば見れる。

献本

丁度その頃に「Windows/Mac/UNIX すべての環境で20年動くプログラムはどう書くべきか」の発売予定が公表された。

そして,発売日直前になって自宅に献本として投函されていた。

びっくりして上記ツイートをしたところ,ここまでに行った書籍への指摘をシェルショッカーが見ていたらしく,それを受けて贈られたようだった。

献本レビュー

ここまでで,一般人である僕が献本されるまでの経緯を説明した。ここからは献本レビューを行う。なお,前述のツイートで指摘した正規表現の解説の間違いは,この書籍の反映には間に合わなかったので,以下の書籍のページで正誤表として掲載されている。

Windows/Mac/UNIXすべてで20年動くプログラムはどう書くべきか

レビュータイトル:「すべてのUNIXで20年動くプログラムはどう書くべきか」改訂第2版

2015-08-04に発売された「すべてのUNIXで20年動くプログラムはどう書くべき」(前著)の内容が増量・洗練されて発売された。書籍の題名が異なっているが,実質的には前著の改訂第2版と考えてよい。

本書はPOSIX原理主義と呼ばれる高い互換性と持続性をもつプログラムの開発手法を実践していくためのテクニック集となっている。POSIX規格に準拠したシェルスクリプトを書くためのテクニックや注意事項,さらに開発したプログラムが紹介されている。

既に前著は読了済みであるため,本書での変更内容に焦点をあてて感想を書いていく。前著の感想は以下に掲載している。

『すべてのUNIXで20年動くプログラムはどう書くべきか デプロイ・保守に苦しむエンジニア達へ贈る[シェルスクリプトレシピ集]』のレビュー 松浦智之 (bkskさん) – ブクログ

本書での追加項目

本書は336ページであり,前著より80ページ多くなっている。それぞれの目次を確認して本書で増えた項目を確認すると,以下となった。

  • 序章
  • 第1章
    • 1-2: /dev/stdin,stdout,stderr
    • 1-3: `〜`(コマンド置換)
    • 1-4: [^〜](シェルパターン)
    • 1-8: set -m(shの-mオプション)
    • 1-10: 最終行の改行は,省略すべきでない
  • 第3章
    • 3-3: bcコマンド
    • 3-7: envコマンド
    • 3-12: iconvコマンド
    • 3-17: odコマンド
    • 3-22: sleepコマンド
  • 第5章
    • 5-8: JSONファイルの生成
    • 5-13: 1秒未満のsleepをする
  • 第6章
    • 6-12: シェルスクリプトでメール送信(添付ファイル付き)
    • 6-13: 他のWebサーバーへのファイルアップロード
    • 6-16: Twitterに投稿する
  • 第7章
    • 7-2: /dev/stderr(inもoutも)なぜかPermission denied
    • 7-6: bashで動かすために注意すべきこと
    • 7-10: trapコマンドでシグナルが捕捉できない

上記の追加内容で大きいと思ったのは,以下の3点だ。

  • 序章
  • 5-8 JSONファイルの生成
  • 5-16 Twitterに投稿する
序章

前著での不満点として参考情報が少ないことがあった。この序章に置いて,POSIXに準拠したシェルスクリプトを書く上で参考になる情報源をいくつも掲載しており,今後勉強していくうえでとてもよかった。

書籍の題名が変わるきっかけとなったWindows 10で導入されたBash on Ubuntu on Windows(BUW)について,導入方法を画面キャプチャー入で丁寧に解説しているのが良かった。まだBUWの導入方法について書籍で説明されているところは多くないように思えるので参考になる。

前著の時点では,POSIX原理主義という開発手法について,理論が完成されていない部分があった。具体的には,POSIX規格の範囲外のWebアプリケーションやネットワーク通信コマンドをどうするかという点だ。この点について,交換可能性というPOSIX原理主義の本質となる考えをきっちりと説明しており,開発手法について参考になった。

5-8 JSONファイルの生成

前著の時点ではJSONのパーサーは解説されていたが,生成方法は存在しなかった。JSONファイルを生成できるようになったということは,POSIX原理主義でWeb APIとの相互通信が可能ということだ。このAPI通信のために外部ライブラリやコマンドに依存せざるを得ない場面があったが,これに依存しなくても済むようになった。JSONファイルの生成はデータの整形が必要で簡単ではないが,一度できればずっと使い続けることができるのでこれは大きい。

5-16 Twitterに投稿する

日本ではTwitterはテレビ番組でも利用されるなど人気が高い。例えば,特定ツイートをかき集めたり,一度に大量のフォローやフォロー解除が可能であったり,更にはcrontabを利用したbotの作成など,シェルスクリプトでツイッターを利用できることはいろんな可能性がある。

また,このTwitterアプリの開発にあたって,データフロー図が掲載されている。今後自分でTwitterアプリを作成するにあたっての参考にもなると思った。

不満点

本書における不満点を述べる。

  1. 内容の重複と値段
  2. Windows/Mac/UNIXの固有の話がない
  3. 体系だった説明の不足
内容の重複と値段

まず,本書は書名自体は変わっているが実質的には前著の改訂第2版という位置づけとみなしてよい。したがって,内容の重複がけっこうある。前著の読者であれば,新しい内容を期待して読むとがっかりするかもしれない。追加された項目以外に内容が改善されている部分もあるのだが,以前読んだ印象が拭えない。

これと合わせて書籍の値段も関係してくる。前著の定価は税抜き2500円だったが,本書は3600円である。ページが80ページ増えたので1ページ約100円で値段が上がったことになる。単純に値段の上昇は買い手にとって好ましくない。まして,前著読者にとっては重複した内容が多いので不満をもつかもしれない。

Windows/Mac/UNIXの固有の話がない

書籍の題名にWindows/Mac/UNIXと書かれており,これらの環境固有の話が出てくるのかと期待した。しかし,序章で書かれたWindows 10のBUWへのインストール方法くらいで,ほぼなかった。例えば,コマンドのオプションが違っていたり,文字エンコーディング・ディレクトリ構成・既定 の設定など,OSごとに注意すべき事項というのがあるのだろうと思う。書名に入れているからにはこうした項目への言及があってもよいと思った。

体系だった説明の不足

これは前著の感想でも書いたが,やはり体系だった説明がほしい。例えば,自分でコマンドを作る場合,引数の解析はどうすればいいか。Webからデータを持ってきたり,引数や入力に何が来るかわからない場合に注意すべきことなど。TIPS集も必要だが,体系だった解説がほしい。

まとめ

POSIXで定義されている正規表現やコマンドの注意点など,この著者のシェルスクリプトに関する書籍を読んでいないのならば,一度は読む価値がある。

個人的には,後半の5-6章で解説されているようなWebサーバーで必要とされるテクニックについては疎い。しかし,特に進歩の早いWebにおいてこれらのテクニックを駆使することで,バージョンアップや環境の変化に悩まされることがなくなる可能性がある。

この本に書かれている内容自体も時間が経過して使えなくなることはないだろう。1冊手元に置いておきたいと思える本だった。

なお,前著読者であれば,著者が同人誌として発売している「Shell Scriptライトックックブック2014-2016」において,本書で追加分の項目がカバーされているので,こちらの購入を検討してもよいかもしれない。

Shell Script ライトクックブック2014-2016 – 松浦リッチ研究所 > 発行物紹介 > 頒布中発行物

全体のまとめ

献本を受けるなんてそうない経験だった。有名人だけが受けることのできるものだと思っていた。自分が疑問に思ったことや間違いを指摘すれば,そこから何か発展することがあるということで一つ印象的な出来事だった。

Windows/Mac/UNIXすべてで20年動くプログラムはどう書くべきか」はPOSIX原理主義を実践していくうえで,その考え方やテクニックがたくさん詰まった書籍となっている。POSIX原理主義に興味を持たれたら購入されてはどうでしょうか?そして,一緒にPOSIX原理主義を実践していきましょう。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です