📘

bashの再実装に取り組んだら地獄を見た件

2023/12/13に公開

bashとは

簡単にいうとシェル、コマンドを実行するソフトウェアです。ターミナルやコマンドプロンプトで実行することが多い、文字だけの黒い画面のアレです。

地獄である所以

変数展開の仕様が複雑

変数展開という機能があり、文字通り変数の中身をコマンド名や引数として渡せる機能なのですが、単に渡すだけじゃないんです。
例えば変数の中にスペースが含まれている場合('a b'など)は、スペースで文字列を区切って、別々の引数として渡します。word splittingという機能です。つまり以下のような実行結果になります。

$ a='  a   b  '; echo $a
a b

空白が消えましたね?そう、空白区切りで引数を渡すので、echoコマンドにはa, bという2つの引数がわたり、echoコマンドは引数を空白区切りで出力するので、元の文字列から空白が一部消えたみたいになります。
このecho $aが変数展開の部分なのですが、これはecho "$a"というように書くと、変数展開はするけどword splittingは行われないという仕様もあります。さらにシングルクォーテーションで囲むとそもそも変数展開されません。ここら辺もすでにめんどいですね。
さらに、word splittingはどの文字で区切るかを環境変数IFSで指定できます。デフォルトは空白とタブ文字などが指定されてます。ややこしいのが、このIFSは変数展開時に「変数の中身をtrim(文字列の両端に連続する特定の文字を消去)する」という機能にも使用されているんです。具体的な仕様はうろ覚えなので割愛しますが、確か「IFSのデフォルト値と上書きされた値で共通する文字は常にtrimするが、word splittingはしない」みたいな変な仕様だった気がします。面倒臭いので常に頭の片隅に残っていましたが、実装しませんでした。

本家のソースコードが読みにくい

bashのソースコードはGitHubにミラー版が上がっており、参照しながら実装したのですが、このソースコードがgoto文とグローバル変数の多様で素人には読めたもんじゃありませんでした。1つの関数自体も数1000行に渡ってたりするし、if文やswitch文の1ブロックも数百行に渡ることもザラです。goto文やグローバル変数のせいで、特殊な処理や変数がどこで設定されているのか追いずらかった記憶があります。読んでみればわかりますが、goto文は本当に読みにくいですね...

C言語つらい

C言語で実装したのですが、オブジェクト指向とかできないし、メソッドみたいなのも使えないので読みにくいコードになってしまいました。工夫のしようはあったのですが、体力的にむりぽでした。

感想

bashを作った人に敬意を持ちつつ、もう二度と実装したくありません。

Discussion