難読化シェル芸の解読: 1

# はじめに
- やばすぎシェル芸が投稿された([@hiroさん](https://twitter.com/hiro_poke91)による)
- 解読がてら[Bashの変数展開](https://gist.github.com/eggplants/9af05967cc21ec0a0d398f9fbecf03d6)や特殊変数の解説をしたい


# 全体
```bash:post
# https://twitter.com/hiro_poke91/status/1218084119504048128
.>&$
"$(<$)"
! __="${_##*. ??}"
$?
___=${__:$_$_:_}${__:~_<<_:_}${__:~_:_}${__:_:_}${__:~_-_:_} __=${__::_}${__:$#$_$#:_}${__:~_<<_:_}${__:$_$#:_}
$___ ${__^^}
(($?=$?))>&$
_=($(<$))
${_[${##}$#>>++_]:~$#}${_[$_$#/++_]::_}${_[_**++_]:~$#}
```
返り値は

```bash:result
# https://twitter.com/minyoruminyon/status/121808415852362957
Fri Jan 17 17:14:26 JST 2020
```
どうやらロケールが英語圏の`date`らしい
？？？なんだこれ　おかしいよ

# 解読開始
## `.>&$`
- これを実行すると`$`というファイルに`.`コマンドのエラー文が書き込まれる

```bash:$
/task.sh: 1 行: .: ファイル名が引数として必要です
.: 使用法: . filename [arguments]
```
- `>&`は`StdOut+StdErr`のリダイレクト

## `"$(<$)"`
- `cmd <file`は`cmd`へ`file`の内容を入力する
- ここでは`<$`のコマンドがないので、`cat`を入力先としているので`$(cat $)`と同値
- そのため`"$の中身"`が実行され変数`_`(後述)に格納される(Thanks:[@qwertanusさん](https://twitter.com/qwertanus))
- ちなみにファイル入出力はどこでやっても良い

```bash:example
echo unko >unko
>unko echo unko
echo >unko unko
```

## `! __="${_##*. ??}"`
- 変数`_`は現在実行しているシェルを格納する(コマンド名とかshファイル名)
- 前の行で実行された`$`の中身が変数`_`に格納されている
- そしてこの行を実行すると変数`__`に`lename [arguments]`が代入される
- `${v##exp}`は`v`の値の`exp`にマッチした部分以降を最長一致で取り出す展開
- ここで入力されたファイル`$`で`*. ??`がマッチするのは以下

```bash:matched
/task.sh: 1 行: .: ファイル名が引数として必要です
.: 使用法: . fi
```
- これ以降の`lename [arguments]`が変数`__`に代入される
- 行頭の`!`は代入後の終了ステータス`0`を否定/反転させ`1`にしている
- よって次行の`$?`が`1`となる(Thanks:[@qwertanusさん](https://twitter.com/qwertanus))

## `$?`
- 変数`?`は直前のコマンドの終了ステータスの参照
- ここでは`1`が返る
- そして`1`という名前のコマンドは当然存在しないので`127`が変数`?`に格納される
- またここで変数`_`に`1`が格納される(次で使用)

## `___=${__:$_$_:_}${__:~_<<_:_}${__:~_:_}${__:_:_}${__:~_-_:_}`
- `$_`は`1`, `$__`は`lename [arguments]`(18文字)
- これを実行すると変数`__`に`unset`が代入される
- `${v:offset:length}`は`v`の値の`offset`のインデックスから`length`文字分切り出す展開
- Pythonだと`v[offset:length]`みたいな
- `~`はビット反転, `<<`は左ビットシフト
- `___=${__:11:1}${__:-4:1}${__:-2:1}${__:1:1}${__:-3:1}`
- よって`___=unset`となる

## `__=${__::_}${__:$#$_$#:_}${__:~_<<_:_}${__:$_$#:_}`
- `$_`は`1`, `$__`は`lename [arguments]`(18文字)
- 変数`#`は関数の引数の数で、今は関数内でないので`0`が返る
- 上と同様に、`__=${__::1}${__:010:1}${__:-4:1}${__:10:1}`
- `010(8)=8(10)`(Thanks:[@hiroさん](https://twitter.com/hiro_poke91))
- `offset`を省略すると0番目からとなる
- よって`__=lang`となる

## `$___ ${__^^}`
- `${v^^}`はvの値の小文字を全て大文字に変換する展開(upcase)
- `unset LANG`となる
- シェル芸Botのロケール(LANGの設定値)は`ja_JP.UTF-8`
- 解除するとコマンドのデフォルトでのロケールで実行されるので`date`が英語に

## `(($?=$?))>&$`
- `(())`は算術演算を行う
- ここでは`$?=$?`は`0=0`となり、`0`に`0`の代入を行う
- 非変数への代入は不正なので、エラーが起き、そのメッセージがファイル`$`に書き込まれる

```bash:$
/task.sh: line 7: ((: 0=0: attempted assignment to non-variable (error token is "=0")
```

## `_=($(<$))`
- `var=()`は配列の宣言
- ここでは`$`の内容がスペースで区切りで配列`_`に代入される
- 参照は`${arr[index]}`で行う

## `${_[${##}$#>>++_]:~$#}${_[$_$#/++_]::_}${_[_**++_]:~$#}`
- `_=('' line 7: ((: 0=0: attempted assignment to non-variable (error token is "=0"))`
- 0番目は空文字列(Thanks:[@hiroさん](https://twitter.com/hiro_poke91))
- `${v:offset}`はvの値のoffsetのインデックスから末尾までを切り出す展開
- `++`はインクリメント, `>>`は右ビットシフト

```bash:terminal
root@628d738436d9:/# echo $[++a]
1
root@628d738436d9:/# echo $[++a]
2
root@628d738436d9:/# echo $[++a]
3
```
- `${#v}`はvの文字列長を返す展開で、vが配列なら`${#v[*]}`で配列の要素数が返る
- `${##}`は`$#`の長さ1が返る
- `${_[10>>1]:-1}${_[10/2]::2}${_[2**3]:-1}`
- `${_[5]:-1}${_[5]::2}${_[8]:-1}`で`date`が返り実行される

# 結論
こわ

# 追記:あわせて読みたい本質情報群
- Hashtag:[#難daコレ](https://twitter.com/search?q=%23%E9%9B%A3da%E3%82%B3%E3%83%AC&src=typed_query)
- Twitter:[自作記号オンリー難読化シェル芸
@hiro_poke91](https://twitter.com/i/events/1141268330973560832)
- 書籍:[難読化シェル芸の世界 ~Bashとすてきな難読化~](https://amazon.co.jp/dp/4839969698)
- ブログ:[難読化シェル芸を発案した - A painter and a black cat](https://raintrees.net/news/95)
- ブログ:[自作の難読化シェル芸リンク集 - /home/jiro4989](https://scrapbox.io/jiro4989/%E8%87%AA%E4%BD%9C%E3%81%AE%E9%9B%A3%E8%AA%AD%E5%8C%96%E3%82%B7%E3%82%A7%E3%83%AB%E8%8A%B8%E3%83%AA%E3%83%B3%E3%82%AF%E9%9B%86)
- ブログ:[難daコレ カテゴリーの記事一覧 - たいちょーの雑記](https://xztaityozx.hatenablog.com/archive/category/%E9%9B%A3da%E3%82%B3%E3%83%AC)
- ブログ:[記号と英字2文字だけでbash - Ryoto's Blog](https://www.ryotosaito.com/blog/?p=178)
- すべて:[GNU Bash Manual - GNU Project](https://www.gnu.org/software/bash/manual/)