今回は前回に続いてファイルの内容を置き換えます。前回は直接コマンドを入力していましたが、今回はシェルスクリプトを利用します。シェルスクリプトを利用すると、より手軽に処理することができます。なお、今回はUNIX系シェルのbash,zshについて説明します。実行結果はmacOS BigSurのものになっていますが、他の環境でも同じように動作するはずです。macOS BigSurのbashのバージョンは3.2と古いままですが、今回の場合は動作には問題ありません。

今回も前回同様に処理するファイルはデスクトップ上にあるsampleディレクトリとします。cd ~/Desktop/sampleとコマンドを入力してカレントディレクトリを変更しておきましょう。

シェルスクリプトを作る

 前回のinfotemp.txtファイル内容の置き換えには以下のsedコマンドを入力しました。

sed s/INFO/営業中/ infotemp.txt > info.txt

・infotemp.txtファイルの内容

 ようこそ喫茶マイナビへ。さまざまなレトロUNIXマシンを用意して、お待ちしております。

INFO

 Tel:00-0000-0000
 url:myna-bee.shop

毎回このコマンドを入力するのは面倒ですから、このままシェルスクリプトにしてしまいましょう。シェルスクリプトにはお約束がありますが、まずは単純にこのコマンドをテキストファイルとして保存します。テキストエディタなどのアプリケーションで作成しても構いませんし、echoコマンドでも構いません。vi(vim)でもEMACSでも好きなもの、使い慣れているもので構いません。
入力が終わったら、このファイルをrep.shという名前で保存します。

ファイルができたら、実行できるようにします。これはファイルに実行権限を付与することで可能になります。実行権限を付与するにはchmodコマンドを使います。chmodの後に+xを指定し、その後に実行権限を付与するファイル名を指定します。

chmod +x rep.sh

実行権限を付与したら、以下のように入力してみましょう。ちなみに./rまで入力しタブキーを押すとシェルの自動入力補完機能が働きます。

./rep.sh

実行するとinfotemp.txtファイルの内容を置き換えたinfo.txtファイルが生成されます。catコマンドで内容を確認してみましょう。

cat info.txt

期待する結果になっているはずです。
このシェルスクリプト程度だと特定のシェルの機能を使っていないので、ほとんどのUNIXシェルで動作するでしょう。しかし、複雑な機能を持つシェルスクリプトでbashの機能を使いたい、zshの機能を使いたい場合には問題が発生してしまうことがあります。

#! (shebang)

特定のシェルでしか動作しないスクリプトの場合、一行目に実行するシェルのパスを書いておく事ができます。必ずしも必要ではなく、書いていない場合は現在実行されているシェル上で実行されます。一行目に実行するシェルのパスではなく実行するプログラムのパスを書いておけば、そのプログラムで実行されます。PerlやRubyなどのプログラム言語のパスを書いておけば、それらのプログラムを実行する事ができます。これをshebangと呼びます。日本語だとシバンとかシェバンとかいろいろ呼び方があるようです。昔懐かしい特撮の宇宙刑事シリーズっぽい名前ですが、調べたらあちらはシャリバンとか機動刑事ジバンとかでした。似てるようで似てない微妙な感じです。どちらも何かを取り締まるという点では似てるかもしれません。

shebangは実行するプログラムのパスを指定する方式なので、シェルやプログラムのバージョン違いにも対応できます。

それではshebangを使ってbashで実行されるようにしてみましょう。shebangである事を示すには一行目の最初が#!から始まる必要があります。いわゆるプログラム関係でありがちなお約束というやつです。ちなみにシェルでは#以後の文字はコメントとして処理されます。コメントなのにコメント扱いされず処理の対象になるものをメタコメントと呼ぶこともあります。プログラム言語ではページ記述言語のPostScriptが同じ方法を採用しています。

多く利用されているbashの場合、以下のように書きます。

#!/bin/bash

現在のMacでデフォルトで採用されているzshだと以下のように書きます。

 #!/bin/zsh

その他のシェルだと以下のようになります。もし、違う場所に入れてある(入っている)なら、そのディレクトリパスを指定します。

#!/bin/sh
#!/bin/csh
#!/bin/tcsh
#!/bin/ksh

シェルではなくてperlやrubyなどスクリプト言語の場合は以下のようになります。ここではmacOS BigSurの例で載せてありますので、異なる環境ではパスが異なる事もあります。

#!/usr/bin/perl
#!/usr/bin/ruby
#!/usr/bin/python

動作確認してみる

 shebangを指定すれば本当に指定したシェルで動作するか確認してみましょう。コマンドラインから動作するシェルを確認する場合、echo $0とすればシェル名が出力されます。しかし、シェルスクリプト内でecho $0とすると実行しているシェルスクリプトのパスが出力されてしまいます。そこで、ps $$とすることで実行しているシェルを確認することにします。$$は現在実行しているプログラムのプロセス番号を示します。psコマンドにパラメーターとして$$を指定すると該当するプロセス情報が表示されます。

それぞれのシェルで実行すると以下のようになります。

#!/bin/sh
ps $$
#!/bin/bash
ps $$
#!/bin/csh
ps $$
#!/bin/tcsh
ps $$
#!/bin/ksh
ps $$
#!/bin/dash
ps $$

shebangを指定したシェルで実行されている事がわかります。期待通りの結果です。

それでは次にスクリプト言語のPerlとRubyでやってみましょう。それぞれの言語特有の命令等を使えば検証できます。まずはPerlから。

#!/usr/bin/perl
$str="Perl lang.\n";
print $str
#!/usr/bin/ruby
str="Ruby lang.";
puts str
#!/usr/bin/python
print("Python lang.");

いずれも期待通りの結果になっています。これとは別に以下のような指定ができます。

#!/usr/bin/env python

このように指定するとpythonの絶対パスを書かなくても、あらかじめ定義されているPATH変数から検索が行われプログラムが実行されます。