記号だけでシェルは操れた

昨日、私は記号と英字2文字だけでbashという論文記事を発表しました。
するとコメントで英字すら使わない画期的な方法を教えていただけたので、改めて共有させて頂きます。

ここまでのおさらい

先のリンクの記事にて、以下のようにdateコマンドを実行できることを発表しました。

$ __=$(($$/$$));___=$(($__+$__));____=$(.|&tr +\(= -$\"%);____=${____##*.};_____=$(${____:$(($___$(($$-$$))-$__)):$__}${____:$___*$___:$__}${____:$(($___$(($$-$$))-$___)):$__} -${____:$__$(($__+$___)):$__}|&tr +\(= -$\"%);_____=${_____##*${____:$(($___$(($$-$$))-$__)):$__}${____:$___*$___:$__}${____:$(($___$(($$-$$))-$___)):$__}};_____=${_____,,};______=($(${____:$(($___*$___)):$__}${_____:$__$(($___*$___)):$__}${____:$(($___*$___+$___)):$__}${____:$(($___+$__)):$__} ${____:$(($___*$___)):$__}${_____:$(($___*$___*$___*$___+$__)):$__}${_____:$(($___*$___*$___-$__)):$__}${_____:$___$(($___*$___)):$__} $(${____:$(($___*$___)):$__}${_____:$(($___*$___*$___*$___+$__)):$__}${_____:$(($___*$___*$___-$__)):$__}${_____:$___$(($___*$___)):$__}  -${____:$(($___*$___)):$__} "{\\${____:$__$(($___*$___)):$__}$(($___*$___+$___))$__..\\${____:$__$(($___*$___)):$__}$(($___*$___*$___-$__))${____:$__$__:$__}}")));_______=($(${____:$(($___*$___)):$__}${_____:$__$(($___*$___)):$__}${____:$(($___*$___+$___)):$__}${____:$(($___+$__)):$__} ${____:$(($___*$___)):$__}${_____:$(($___*$___*$___*$___+$__)):$__}${_____:$(($___*$___*$___-$__)):$__}${_____:$___$(($___*$___)):$__}  $(${____:$(($___*$___)):$__}${_____:$(($___*$___*$___*$___+$__)):$__}${_____:$(($___*$___*$___-$__)):$__}${_____:$___$(($___*$___)):$__}  -${____:$(($___*$___)):$__} "{\\${____:$__$(($___*$___)):$__}$(($___*$___))$__..\\${____:$__$(($___*$___)):$__}$(($___*$___+$__))${____:$__$__:$__}}")));${______[$(($__+$___))]}${______[$(($$-$$))]}${______[$(($___$(($$-$$))-$__))]}${______[$(($___*$___))]}
Wed Feb 20 15:11:00 UTC 2019

このワンライナーには、英字を用いたコマンドtrを2回も使ってしまうという重大な問題点を抱えていました。

解決手段

コメントでyamayaさんに教えていただきました。

 $(.|&tr …) を $(.>&/???/??/$__) に変えてもいいです。

これを利用すると以下のようになりました。

$ __=$(($$/$$));___=$(($__+$__));____=$(.&>/???/??/$__);____=${____##*.};_____=$(${____:$(($___$(($$-$$))-$__)):$__}${____:$___*$___:$__}${____:$(($___$(($$-$$))-$___)):$__} -${____:$__$(($__+$___)):$__}&>/???/??/$__);_____=${_____##*${____:$(($___$(($$-$$))-$__)):$__}${____:$___*$___:$__}${____:$(($___$(($$-$$))-$___)):$__}};_____=${_____,,};______=($(${____:$(($___*$___)):$__}${_____:$__$(($___*$___)):$__}${____:$(($___*$___+$___)):$__}${____:$(($___+$__)):$__} ${____:$(($___*$___)):$__}${_____:$(($___*$___*$___*$___+$__)):$__}${_____:$(($___*$___*$___-$__)):$__}${_____:$___$(($___*$___)):$__} $(${____:$(($___*$___)):$__}${_____:$(($___*$___*$___*$___+$__)):$__}${_____:$(($___*$___*$___-$__)):$__}${_____:$___$(($___*$___)):$__}  -${____:$(($___*$___)):$__} "{\\${____:$__$(($___*$___)):$__}$(($___*$___+$___))$__..\\${____:$__$(($___*$___)):$__}$(($___*$___*$___-$__))${____:$__$__:$__}}")));_______=($(${____:$(($___*$___)):$__}${_____:$__$(($___*$___)):$__}${____:$(($___*$___+$___)):$__}${____:$(($___+$__)):$__} ${____:$(($___*$___)):$__}${_____:$(($___*$___*$___*$___+$__)):$__}${_____:$(($___*$___*$___-$__)):$__}${_____:$___$(($___*$___)):$__}  $(${____:$(($___*$___)):$__}${_____:$(($___*$___*$___*$___+$__)):$__}${_____:$(($___*$___*$___-$__)):$__}${_____:$___$(($___*$___)):$__}  -${____:$(($___*$___)):$__} "{\\${____:$__$(($___*$___)):$__}$(($___*$___))$__..\\${____:$__$(($___*$___)):$__}$(($___*$___+$__))${____:$__$__:$__}}")));${______[$(($__+$___))]}${______[$(($$-$$))]}${______[$(($___$(($$-$$))-$__))]}${______[$(($___*$___))]}
Fri Feb 22 09:11:01 UTC 2019

記号しか出てこない!なんと美しい…
ご指摘いただきありがとうございました。

解説

Bashのmanを見ると以下のように書かれています。

This construct allows both the standard output (file descriptor 1) and the standard error output (file descriptor 2) to be redirected to the  file whose name is the expansion of word.
There are two formats for redirecting standard output and standard error:
      &>word
and
      >&word
Of the two forms, the first is preferred.  This is semantically equivalent to
      >word 2>&1

簡単にいうと、「&>word>&wordを書くと、標準出力も標準エラー出力もwordっていうファイルに書き出してあげるよ」ということです。

そして、標準出力を表すファイルといえば、/dev/fd/1

そう。ワイルドカードを使えばこのデバイスファイルを一意に記述できてしまうんです。

$ __=$(($$/$$)) # $__には1が代入される
$ echo /???/??/$__
/dev/fd/1

これには背筋凍りましたね…
これらの技を組み合わせたら

$ __=$(($$/$$))
$ ___=$(.&>/???/??/$__) # stderr->stdin->$___
$ ___=${___##*.}
$ echo $___
filename [arguments]

記号だけでfilename [arguments]が取得できました。

まとめ

記号難読化シェル芸よ、永遠に。

記号だけでシェルは操れた」への6件のフィードバック

  1. dateです。お納めください。

    _(){ __=$@;};_ /*/$$/../*-*;_ ${__##*-};$(${__%?????} !-: ^-~<<<"'\$${#__}(")

  2. 古い人間ですいません。最近の環境では動かないみたいですね。

    _(){ __=$@;};_ /*/$$/../?????-*;_ ${__##*-};$(${__%?????} !-: ^-~<<<"'\$${#__}(")

    これで動きますかね?

    それからhello worldですがまた異なる手法で記号化したものもあります。
    http://golf.shinh.org/reveal.rb?Hello+broken+keyboard/yamaya%28sym%29_1347623599&sh
    これは単に記号化するだけでなく、使う記号の種類をできるだけ減らすことを目指したものです。

    1. ようやくこのコードの意味するところがわかりました…
      とんでもないですねこれ…
      リンクもありがとうございます…!

    2. yamayaさん

      1,2,A,zと記号でdateコマンドしていたkanataと申します。
      お話したいことがあり、メールさせて頂きました。
      確認いただけると幸いでございます。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です