shebang に対応しているプログラミング言語まとめ

# はじめに

https://qiita.com/rana_kualu/items/84f66fe970f7feccf367

この記事を読んで、 **javascript(ECMA Script, ES2023) において shebang が言語仕様となる** ことを初めて知りました。

shebang を shell 以外に使うことに関しては、UNIX(OS) 側が、**「スクリプト言語は `#` をコメントとして扱うことが一般的」** ということを想定した、限定的な使用法と私は認識しています。

そのため、 **`#` をコメントとして使用しないプログラミング言語からの視点** でこの仕様を考えると、（UNIX のスクリプト実行のフォーマットという） **プログラミング言語が用意している実行方法の範囲から外れたケースの考慮** となります。
Node.js は、実行環境も含めたアプリケーションなので、 **Node.js に shebang の考慮が入っていること自体には違和感を強くはもたない** のですが、ブラウザの実行も含めた **ECMA Script の視点で shebang の考慮が仕様に入ることには、少し違和感がある** と感じました。

では、この感覚は一般的なのでしょうか？

この問いに対する、正解があるわけではありません。
ただ、目安として、 **`#` をコメントとして使用してない プログラミング言語 は shebang に対応することが多いのか** を知りたいと思いました。

本記事では、簡易的に調査した結果を記載します。

# 調査方法と判定など

- 各プログラミング言語の環境は、 **オンラインの [paiza.IO](https://paiza.io/ja/projects/new)** を使用します。
- 記事執筆時点で paiza.IO のデフォルト状態で選択可能なものを調査対象のプログラミング言語 として扱います。
- paiza.IO では、 `MySQL` などの 汎用プログラミング言語として一般的に扱われないものも含まれますが、本記事中では区別することなく、プログラミング言語として扱います。
- バージョンや環境を含めて、 **paiza.IO の挙動が正しいと定義** します。つまり、調査結果は **当該プログラミング言語の一般的な仕様との差異がある** かもしれません。
- 判定には、paiza.IO で言語選択をした時に表示されるプログラムから、以下のみを変更したプログラムの実行結果を用います
  - `#!/usr/bin/env hoge` を **行頭** に書いたプログラム
  - `#!/usr/bin/env hoge` を **2行目** に書いたプログラム（先頭は空行）
- 前述の2つのプログラミングの結果から、以下の3パターンに分類します
  - 両方のプログラムの結果が、差異がなく正常終了した場合
    - `#!がコメント` と判定
  - 両方のプログラムの結果が、両方とも異常終了した場合
    - `shebang対応無し` と判定
  - 上記以外、つまり、プログラミングの結果に差異がある場合
    - `shebang対応有り` と判定

# 結果

まずは、上記のルールで 31言語を実施した結果を記載します。

|#|プログラミング言語|結果|備考|
|:-:|:--|:--|:--|
|1|Bash|`#!がコメント`|-|
|2|C|`shebang対応無し`|-|
|3|C#|`shebang対応無し`|-|
|4|C++|`shebang対応無し`|-|
|5|Clojure|`#!がコメント`|`#` ではコメントではない|
|6|Cobol|`#!がコメント`|-|
|7|CoffeeScript|`#!がコメント`|-|
|8|D|🎯 `shebang対応有り`|-|
|9|Elixir|`#!がコメント`|-|
|10|Erlang|`shebang対応無し`|-|
|11|F#|🎯 `shebang対応有り`|2行目だと `error FS0000: #! may only appear as the first line at the start of a file.` という内容のメッセージ|
|12|Go|`shebang対応無し`|-|
|13|Haskell|`#!がコメント`|`#` ではコメントではない|
|14|Java|`shebang対応無し`|-|
|15|JavaScript|🎯 `shebang対応有り`|-|
|16|Kotlin|🎯 `shebang対応有り`|-|
|17|MySQL|`#!がコメント`|-|
|18|Nadesiko|`#!がコメント`|-|
|19|Objective-C|`shebang対応無し`|-|
|20|Perl|⚠️ `shebang対応有り`|`#` 自体はコメントとして扱われるが1行目に描いた場合 `/usr/bin/env: ‘hoge’: No such file or directory` が発生。|
|21|PHP|🎯 `shebang対応有り`|`<?php` 内ではコメント扱い。ファイルの先頭(`<?php`外)では1行目のときのみ出力が消える|
|22|Python2|`#!がコメント`|-|
|23|Python3|`#!がコメント`|-|
|24|R|`#!がコメント`|-|
|25|Ruby|⚠️ `shebang対応有り`|`#` 自体はコメントとして扱われるが1行目に描いた場合 `ruby: no Ruby script found in input (LoadError)` が発生。|
|26|Rust|🎯 `shebang対応有り`|-|
|27|Scala|`shebang対応無し`|-|
|28|Scheme|🎯 `shebang対応有り`|-|
|29|Swift|🎯 `shebang対応有り`|-|
|30|TypeScript|🎯 `shebang対応有り`|2行目だと `error TS18026: '#!' can only be used at the start of a file.` という内容のメッセージ|
|31|VB|`shebang対応無し`|-|

実行してみると、想定外の挙動をするものがありました

- `Clojure` と `Haskell` は筆者が経験が無いので挙動のみからの確認だが、 `#` のみではコメントではないのだが、 `#!` はコメントとして扱われていそう
- `Perl` や　`Ruby` などは、`#` はコメント扱いだが、 paiza.io の環境では shebang によりエラーが発生した。（実行環境の問題の可能性が高いため、 これらを 『⚠️ `shebang対応有り`』と表記）
- `F#` と `TypeScript` は、エラーメッセージを含めて shebang を想定した動作をした

集計した数字は以下の通り

- `#` がコメントではない言語のうち、shebang対応してる言語は、 9 / 18となり半数
  -  『`shebang対応無し`』 が9個(C, C#, C++, Erlang, Go, Java, Objective-C, Scala, VB)
  - 『🎯 `shebang対応有り`』が9個(D, F#, JavaScript, Kotlin, PHP, Rust, Scheme, Swift, TypeScript)
- `#` がコメントの言語数は 11 / 31。(Bash, Cobol, CoffeeScript, Elixir, MySQL, Nadesiko, Perl, Python2, Python3, R, Ruby)

# 感想

コンパイルが必要な言語か？（非スクリプト言語か？）という観点も考えられますが、分類が確定的でない事と paiza.IO などの簡易的に実行できる環境もあることを考えて、今回は除きました。

その上で、 『`shebang対応無し`』 が9個に対し 『🎯 `shebang対応有り`』が9個という結果は、「スクリプトとして用いられる言語であれば考慮に値する」くらいの結果かと個人的に思いました。(想定より少し多かった)
今後、プログラミング言語や実行環境を作る人のご参考になればと思います。

本題とはそれますが、shell以外の 単独で実行可能なスクリプトファイルの shebang を書くか、書かないかと言う話もあるかと思います。

私自身、ファイルの拡張子から実行ファイルの形式が判断できることと、 shebang 自体に環境依存があることから、あまり書きたくないなという気分にはなる一方、気軽に実行可能形式ファイルとして保存できるため、結局書くことが多かったりします。

これも、「スクリプトとして用いられるファイルであれば気軽に書いてよい」くらいに考えても良いのかな、と思ったりしました。