記憶力が無い

プログラミングとランニングとカメラと何か

Bashでクワイン(Quine)を作る

連休何も予定がなく時間を持て余しているので、Bashのクワインについて考えてみました。

クワイン(Quine)とは

クワイン (プログラミング) - Wikipedia

自分自身と同じ文字列を表示するプログラムをクワイン(Quine)といいます。

Bashでクワイン(Quine)を作る

最初に示したクワインが出来上がるまでの考えを、順を追って解説してみます。

ベース

echoecho を表示するものをベースにします。

$ echo 'echo hoge'
echo hoge

eval を導入

ベースの hoge の部分を変数化します。 そのままだと変数 $a が展開されないので eval を導入します。

$ a='echo $a';$a
$a
$ a='echo $a';eval $a
echo $a

表示の調整

元のプログラムに近づくように表示を調整します。

$ a='echo a="$a;eval \$a"';eval $a
a=echo a="$a;eval \$a";eval $a

シングルクオートを表示する

Bash ではシングルクオート内でシングルクオートが使えないため、 苦肉の策として変数にシングルクオートを突っ込みます。

$ a='echo a="$b$a$b;b=\\$b;eval \$a"';b=\';eval $a
a='echo a="$b$a$b;b=\\$b;eval \$a"';b=\';eval $a
$ a='echo a="$b$a$b;b=\\$b;eval \$a"';b=\';eval $a | bash
a='echo a="$b$a$b;b=\\$b;eval \$a"';b=\';eval $a

完成!

シングルクオートの扱いについて

シングルクオートを表示するには ASCII コードを使うという方法もあります。 echo では e オプションを使って次のように書くとシングルクオートが表示されます。

$ echo -e \\x27
'

これを上記のクワインに組み合わせると、次のようになります。

$ a='echo a="$(echo -e \\x27)$a$(echo -e \\x27);eval \$a"';eval $a
a='echo a="$(echo -e \\x27)$a$(echo -e \\x27);eval \$a"';eval $a

本当は次のようにしたいのですが、 \x27 と表示されてほしいところもシングルクオートになってしまうため、 苦肉の策で $(echo -e \\x27) としています。

$ a='echo -e a="\x27$a\x27;eval \$a"';eval $a
a='echo -e a="'$a';eval \$a"';eval $a

qiita.com

こちらの記事にある例では、 printf を使っているようです。 こっちの方が echo を使うよりも若干文字数が削減できますね。

$ printf \\x27
'
$ printf \\47
'

eval を使わずにできるか

上で紹介した記事でも同じように、コマンド文字列を変数に代入 + eval というアプローチをしていました。 それでは、eval を使わずにクワインを作ることはできるのでしょうか。

...と思って数時間あれこれ考えてみましたが、eval を使わないクワインは思いつきませんでした。

作れる作れないの話は、理論計算機科学の話になりそうですが、もうその辺の特徴づけがあったりするんですかね?

長くなりそうなのでこの話はこの辺で...(知ってる方がいればコメントください)

Copyright © 2017 ttk1