ハッシュのストレッチングみたいなことをbashでできたら面白いかなと思って調べてたのだけど、特定のコマンドにパイプでn回値を渡す、というような処理はちょっと書くのが難しいようで、以下のようにforとか使ってやる必要があるみたいだ。
# 'Hello World!Yeah!'を3回sha256でストレッチングするという処理をしてる
echo 'Hello World!Yeah!' | (read v; for i in {1..3};do v=$(echo $v | (sha256sum|awk '{print $1}'));done;echo $v;)
echo 'Hello World!Yeah!' | (sha256sum|awk '{print $1}') | (sha256sum|awk '{print $1}') | (sha256sum|awk '{print $1}')
[root@BS-PUB-CENT7-01 ~]# # 'Hello World!Yeah!'を3回sha256でストレッチングするという処理をしてる
[root@BS-PUB-CENT7-01 ~]# echo 'Hello World!Yeah!' | (read v; for i in {1..3};do v=$(echo $v | (sha256sum|awk '{print $1}'));done;echo $v;)
13ee5ecfc8a123d816aae799d5233281622ef66d88a3f4e3a8a86655452218b4
[root@BS-PUB-CENT7-01 ~]#
[root@BS-PUB-CENT7-01 ~]# # 同じ処理をパイプで
[root@BS-PUB-CENT7-01 ~]# echo 'Hello World!Yeah!' | (sha256sum|awk '{print $1}') | (sha256sum|awk '{print $1}') | (sha256sum|awk '{print $1}')
13ee5ecfc8a123d816aae799d5233281622ef66d88a3f4e3a8a86655452218b4
一応、回数も数字で指定できるし、悪くはないけどforということでシングルタスクというのもあるからか、どことなくレスポンスが遅い。
[root@BS-PUB-CENT7-01 ~]# time echo 'Hello World!Yeah!' | (read v; for i in {1..3};do v=$(echo $v | (sha256sum|awk '{print $1}'));done;echo $v;)
13ee5ecfc8a123d816aae799d5233281622ef66d88a3f4e3a8a86655452218b4
<span style="color: #ff0000;">real 0m0.544s</span>
user 0m0.003s
sys 0m0.014s
[root@BS-PUB-CENT7-01 ~]# time echo 'Hello World!Yeah!' | (sha256sum|awk '{print $1}') | (sha256sum|awk '{print $1}') | (sha256sum|awk '{print $1}')
13ee5ecfc8a123d816aae799d5233281622ef66d88a3f4e3a8a86655452218b4
<span style="color: #ff0000;">real 0m0.114s</span>
user 0m0.003s
sys 0m0.009s
これではちょっと面白く無いよねということで、数字での回数指定はできないけれどブレース展開を使ってパイプをつなげ続けるのと同等の処理をさせてみた。 以下、実行例。
eval $(set echo\ 'Hello World!Yeah!' '(sha256sum|awk "{print \$1}")'{,,};IFS=\|;echo "$*")
[root@BS-PUB-CENT7-01 ~]# echo $(set echo\ 'Hello World!Yeah!' '(sha256sum|awk "{print \$1}")'{,,};IFS=\|;echo "$*")
echo Hello World!Yeah!|(sha256sum|awk "{print \$1}")|(sha256sum|awk "{print \$1}")|(sha256sum|awk "{print \$1}")
[root@BS-PUB-CENT7-01 ~]# eval $(set echo\ 'Hello World!Yeah!' '(sha256sum|awk "{print \$1}")'{,,};IFS=\|;echo "$*")
13ee5ecfc8a123d816aae799d5233281622ef66d88a3f4e3a8a86655452218b4
[root@BS-PUB-CENT7-01 ~]# time eval $(set echo\ 'Hello World!Yeah!' '(sha256sum|awk "{print \$1}")'{,,};IFS=\|;echo "$*")
13ee5ecfc8a123d816aae799d5233281622ef66d88a3f4e3a8a86655452218b4
real 0m0.174s
user 0m0.004s
sys 0m0.010s
ちょっとわかりにくい書き方になってしまうのだが、まぁ回数増やすのにはカンマ(,)足すだけだし、悪くは無さそう。 ちなみに、試しにパイプを通してコマンドを実行する回数を10回くらいにした場合のパフォーマンスはこんな感じ。
[root@BS-PUB-CENT7-01 ~]# time echo 'Hello World!Yeah!' | (read v; for i in {1..10};do v=$(echo $v | (sha256sum|awk '{print $1}'));done;echo $v;)
6b88b3fa44e36e030c175b5d53139079e7f660712c4ae005174dc2fcabe1a4f5
<span style="color: #ff0000;">real 0m1.689s</span>
user 0m0.009s
sys 0m0.036s
[root@BS-PUB-CENT7-01 ~]# time echo 'Hello World!Yeah!' | (sha256sum|awk '{print $1}') | (sha256sum|awk '{print $1}') | (sha256sum|awk '{print $1}') | (sha256sum|awk '{print $1}') | (sha256sum|awk '{print $1}') | (sha256sum|awk '{print $1}') | (sha256sum|awk '{print $1}') | (sha256sum|awk '{print $1}') | (sha256sum|awk '{print $1}') | (sha256sum|awk '{print $1}')
6b88b3fa44e36e030c175b5d53139079e7f660712c4ae005174dc2fcabe1a4f5
<span style="color: #ff0000;">real 0m0.158s</span>
user 0m0.008s
sys 0m0.034s
[root@BS-PUB-CENT7-01 ~]# time eval $(set echo\ 'Hello World!Yeah!' '(sha256sum|awk "{print \$1}")'{,,,,,,,,,};IFS=\|;echo "$*")
6b88b3fa44e36e030c175b5d53139079e7f660712c4ae005174dc2fcabe1a4f5
<span style="color: #ff0000;">real 0m0.206s</span>
user 0m0.008s
sys 0m0.033s
単純にパイプつなげただけの処理には及ばないものの、単純にforを使った処理に比べたらかなり早いようだ。