断捨離
随分前に書いた、コレに続いて。
あ、Windows での挙動には触れない。
perlとruby
$ cat hoge.pl
# !/bin/bash
find . -type f | perl -x $0
exit 0
# !/usr/bin/env perl -ln
print ;
$ perl hoge.pl
./bar
./foo
./hoge
.
.
.
1. perl は、インタプリタを解釈してくれる。
#! 行に "perl" や "indir" という語が含まれていなければ、#! の後に 指定されたプログラムが Perl インタプリタの代わりに実行されます。 これは少し変わっていますが、#! が行なえないマシンを使っている方には 有効でしょう; プログラムに対して使っている SHELL が /usr/bin/perl だと 言っておけば、Perl が正しいインタプリタを起動してくれるからです
(perlrunより引用)
つまり、
$ cat hoge.rb
# !/usr/bin/env ruby
puts("ruby")
$ perl hoge.rb
ruby
$ cat hoge.sh
# !/bin/bash
echo bash
$ perl hoge.sh
bash
2. ruby は、インタプリタが複数書かれてたら、ruby まで読み飛す。
コマンドラインに指定したスクリプトが
#!
で始まるファイルで、その行にruby
という文字列を含まない場合、その行を読み飛ばします。#!
に続く 文字列がruby
という文字列を含む行を見つけたらその行以下を Ruby スク リプトとして実行します。
(rdocより引用)
$ cat hoge2.sh
# !/bin/bash
echo bash
ruby -x $0
exit 0
# !/usr/bin/env ruby
puts("ruby")
の場合、
$ ruby hoge2.sh
ruby
3. perl も ruby も -x によって、解析開始を遅らす事が出来る。
-x スイッチを 指定した場合には、まず、最初に #! と "perl" という文字列を 含む行を探し、そこから解析を始めます。 これは、大きなテキストにプログラムを埋め込んで、実行するようなときに便利です。 (この場合、プログラムの終わりは、トークン END を使って 示すとよいでしょう。)
(perlrunより引用)
ruby の方も rdoc に同様の事が明記してある。
てなわけで、A のコードが成立する。
ruby の B でも
$ bash hoge2.sh
bash
ruby
なので、こう言うことも出来る。
$ cat hoge3.sh
# !/bin/bash
echo bash
perl -x $0
ruby -x $0
exit 0
# !/usr/bin/env perl
print("perl\n") ;
__END__
# !/usr/bin/env ruby
puts("ruby")
__END__
$ bash hoge3.sh
bash
perl
ruby
$ perl hoge3.sh
bash
perl
ruby
$ ruby hoge3.sh
ruby
追記
って書いたけど、
改めて読みなおしたら、 ruby の場合 -x の存在意義って無いなあ?
何の為だろう、、、windows の為だろうか、、、
# !/bin/bash
ruby -x $0
exit 0
# !/usr/bin/env ruby
puts("ruby")
^D # コントロール + V、コントーロル + D で埋め込み(mac のターミナル)
puts("test")
$ bash tsuiki.sh
ruby
$ ruby tsuiki.sh
ruby
pythonの場合
python の場合は、-x があるものの、かなりの制限を掛けて、「一行のみ飛ばすだけですよーーー」と明記してある。
-x(原文)
Unix 以外の形式の #!cmd を使うために、ソースの最初の行をスキップします。これは、DOS専用のハックのみを目的としています。
(ドキュメントより引用)
とは言え、無理をすれば、
$ cat hoge4.sh
find . -type f | python -x $0 ; exit 0
# !/usr/bin/env python
import sys
for line in sys.stdin:
print(line.strip())
$ bash hoge4.sh
./bar
./foo
./hoge
.
.
.
みたいな事が出来なくもない。