はじめに
全体
post
# https://twitter.com/hiro_poke91/status/1218084119504048128
.>&$
"$(<$)"
! __="${_##*. ??}"
$?
___=${__:$_$_:_}${__:~_<<_:_}${__:~_:_}${__:_:_}${__:~_-_:_} __=${__::_}${__:$#$_$#:_}${__:~_<<_:_}${__:$_$#:_}
$___ ${__^^}
(($?=$?))>&$
_=($(<$))
${_[${##}$#>>++_]:~$#}${_[$_$#/++_]::_}${_[_**++_]:~$#}
返り値は
result
# https://twitter.com/minyoruminyon/status/121808415852362957
Fri Jan 17 17:14:26 JST 2020
どうやらロケールが英語圏のdateらしい
???なんだこれ おかしいよ
解読開始
.>&$
- これを実行すると
$というファイルに.コマンドのエラー文が書き込まれる
$
/task.sh: 1 行: .: ファイル名が引数として必要です
.: 使用法: . filename [arguments]
-
>&はStdOut+StdErrのリダイレクト
"$(<$)"
-
cmd <fileはcmdへfileの内容を入力する - ここでは
<$のコマンドがないので、catを入力先としているので$(cat $)と同値 - そのため
"$の中身"が実行され変数_(後述)に格納される(Thanks:@qwertanusさん) - ちなみにファイル入出力はどこでやっても良い
example
echo unko >unko
>unko echo unko
echo >unko unko
! __="${_##*. ??}"
- 変数
_は現在実行しているシェルを格納する(コマンド名とかshファイル名) - 前の行で実行された
$の中身が変数_に格納されている - そしてこの行を実行すると変数
__にlename [arguments]が代入される -
${v##exp}はvの値のexpにマッチした部分以降を最長一致で取り出す展開 - ここで入力されたファイル
$で*. ??がマッチするのは以下
matched
/task.sh: 1 行: .: ファイル名が引数として必要です
.: 使用法: . fi
- これ以降の
lename [arguments]が変数__に代入される - 行頭の
!は代入後の終了ステータス0を否定/反転させ1にしている - よって次行の
$?が1となる(Thanks:@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さん) -
offsetを省略すると0番目からとなる - よって
__=langとなる
$___ ${__^^}
-
${v^^}はvの値の小文字を全て大文字に変換する展開(upcase) -
unset LANGとなる - シェル芸Botのロケール(LANGの設定値)は
ja_JP.UTF-8 - 解除するとコマンドのデフォルトでのロケールで実行されるので
dateが英語に
(($?=$?))>&$
-
(())は算術演算を行う - ここでは
$?=$?は0=0となり、0に0の代入を行う - 非変数への代入は不正なので、エラーが起き、そのメッセージがファイル
$に書き込まれる
$
/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さん)
-
${v:offset}はvの値のoffsetのインデックスから末尾までを切り出す展開 -
++はインクリメント,>>は右ビットシフト
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が返り実行される
結論
こわ