「#!」 (SheBang)の語源を徹底追求 「切り刻んでビックリ」

「#!URL」エントリーに対するツイートやコメントで#!という文字列自体に対する疑問などが意外とあったので、ここでまとめてみる。

#!とは…

  • ウェブとUnixで違った意味を持つ
  • "shebang"と綴られる
  • Hash(#) Bang(!)の略
  • グーグル検索tips: "#!"では何も出ない。"shebang"で検索するといい。

Unixでは昔からスクリプトファイルでインタプリタを指定する最初のラインに使われてきた

例えば
~/bin/ohhaiを


#!/usr/bin/python
print "OH HAI"
とすればpython hoge.pyとしなくても直接コマンドとして使える

$ ohhai
OH HAI
このようにスクリプトファイルの一行目でインタプリタを指定する行頭に使う。詳しくはここを参照 http://ja.wikipedia.org/wiki/%E3%82%B7%E3%83%90%E3%83%B3_(Unix) 「シバン」という発音もここにあった。

上記の例スクリプトファイルに実行権限が必要となる。
$ chmod a+x ~/bin/ohhai
あと、スクリプトのあるディレクトリがパスに入っていないと上のようにコマンド名だけでは実行できない。
$ ~/bin/ohhai
とするか
$ PATH=${PATH}:~/bin; ohhai
とでもする

URLに入っている#!はサーバに送られる部分とAjaxアプリが管理する部分にURLを分割する

(この手法でサイト作ったことなくブログから学んだ知識なので嘘があったらコメントやツイッターで叱ってください)

  • 昔から#以降はフラグメントと呼ばれ、ページ内のセクションに対するリンクだった
  • #から左しかサーバにリクエストとして送られない: http://example.com/page1#section1 というURLがあるとする…
    • ブラウザはサーバにhttp://example.com/page1をリクエストする
    • 返ってきたページ中で"section1"という名のエレメントを見付けてそこに移動する
    • つまり#から右のフラグメントはブラウザが解釈する部分ということになっている
    • これに注目したJavaScriptハッカーは…
  • Ajaxアプリケーションで「ページ」の状態を管理しブックマークできるようにするのにフラグメントを使うようになる
    • その結果クロールできないコンテンツが増える
  • グーグルがこのようなサイトをクロール可能にするスペックを提案。「#!」を分離シーケンスとして選択。
    • URLに#!があったらボットは#!以降の部分をクエリストリングとしてサーバにリクエストするというサイトとグーグルボットの間の決まり事
    • #!はブラウザにとってはたまたま!で始まるフラグメントで特別な意味をもたない
  • 多くのサイトがグーグルインデックスにのりたいのでAjaxでは#!を使うのが一般的になる

既存のフラグメントURLをAjax URLとしてクロールしてしまうと不味いので、グーグルはそれまでのURLにあまり見られない「#!」というシーケンスを特別扱いにするようにしたのだと思う。

URLに#が入っていたらこう読めばいいのでは: (ゲストさんの提案)

  • #だけの場合は伝統的なフラグメント
  • #!のときはAjaxアプリケーション用URL

shebangの語源

"shebang"は"Hash Bang"の略。#=Hash、!=Bangだ。「#」は"sharp sign"とか"number sign"が正式名称。「!」は正式には"exclamation sign"。でも"number sign,exclamation sign"というのはいかにも長い。なので当然簡略化される。
しかし何故hashとbangが選択されたのだろうか?

「!」がBangと呼ばれる由来

"Bang"は「!」の俗称だ。叩いたり銃を撃ったりしたときの音の擬声語からビックリマークを意味することになったんだと思う。

「#」がHashと呼ばれる由来

「#」をハッシュと呼ぶのは元々北米以外の英語圏での慣習らしい。hashは一般的には「切り刻んで混ぜる」とい意味がある。「hash関数」もこの意味に由来する。http://en.wikipedia.org/wiki/Hash_function#Origins_of_the_term

"Hashbrown"を見ると「#」がローマ字の中で一番それに近い:
http://www.flickr.com/photos/nycblondieandbrownie/3283983540/
だから#がHashと呼ばれるようになったのだろうと解釈している。Unix(コンピュータ科学)においては切り刻むハッシュ関数の意味からイギリス風の"hash"という呼び方が定着したと思われる。

#! --> Hash Bang --> SheBang となったのは:

  • # --> 切り刻む --> Hash
  • ! --> びっくりする --> 銃声 --> Bang

SheBangは「切り刻んでビックリ」だ

shebangのバリエーション

shell bangからという説もある

  • she-bang
  • sh-bang
  • sha-bang

Dennis Ritchie先生よると

BSDカンファレンスでそのアイデアを得た。 … 名前についてはイギリス風だが記述的な"hash-bang"と呼んでいたと思う。でもニックネームで呼んでいた記憶はない。」 {link..}

何故#!がスクリプト用のマジックナンバーになったか

「#!」は人間が読めるマジックナンバーということになっている。
http://ja.wikipedia.org/wiki/%E3%83%9E%E3%82%B8%E3%83%83%E3%82%AF%E3%83%8A%E3%83%B3%E3%83%90%E3%83%BC_(%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%A0)

では何故「#!」がスクリプトマジックナンバーとなったか? これに説明しる資料はまだ見付かっていないので、推測になる。

このコンテキストで重要なUnix初期のスクリプト言語においては「#」がコメントキャラクタとして使われていた。シェルやawkなどがそうだ。
インタプリタがコメントとして扱うシーケンスをマジックナンバーとしれば、コマンドとなるスクリプトファイルを明示的にインタプリタに渡しても問題なく実行できる。だからコメントキャラクタの「#」がマジックナンバーの頭に採用されたのだろう。
つまりマジックナンバーがコメントキャラクタでないとこの二つが両立しない:
$ ./hello.py
$ python hello.py

では「!」は? ビックリマークは「これをやれ!」という命令形を連想させる。命令形の構文で「!」を使う例は色々なコンピュータ文化で見られる。例えばUnixシェルでは「!!」が過去のコマンドを実行するのに使われる。関数型言語schemeでは(set!)のように副作用のあるimperative(命令形)文の関数(マクロ)のお尻に「!」を付ける習慣がある。

だから「#!」にはこう読む:

この行は…

Dennis先生はこのようなイメージで「#!」を選んだのだろう。

まとめ

語源なんかわからなくても使えればいいのだが、知っておく何かスッキリして気持よくなる。読者の皆様のちょっとモヤモヤっとしたものが晴れてくれれば仕事をほったらかしてこのエントリーを書いたことがむくわれる。