クラウドワークス エンジニアブログ

日本最大級のクラウドソーシング「クラウドワークス」の開発の裏側をお届けするエンジニアブログ

Bashでくるくるさせる

クラウドソーシングで最大手のクラウドワークスで主にコンテンツマーケをやっています、KIMIです。

いい加減Zshを使えという声が聞こえてきそうですが、Bashの話です。

結論から

Bashでくるくるですが、いろいろ調べた結果次のようになりました。

$ cat hoge.sh
#!/bin/bash

spin() {
  local chars=('/' '-' '\' '|') i=0 mod=0

  while :
  do    
    echo -ne ${chars[mod]} "\r"
    mod=$(( ++i % ${#chars[@]} ))
    sleep .1
  done
}

spin

f:id:cw_kimi1:20160624123803g:plain

詳しく見ていきます。

配列

生成する
$ bash --version
GNU bash, version 3.2.57(1)-release (x86_64-apple-darwin15)
Copyright (C) 2007 Free Software Foundation, Inc.
$ echo $SHELL
/bin/bash
$ array=(a b c)
$ echo ${array[0]}
a
$ echo ${array[1]}
b
$ echo ${array[2]}
c
素数
$ echo ${#array[@]}
3
Join

くるくるとは関係ないけど、特殊シェル変数IFS を使って Join のようなこともできます。

$ IFS=, echo "${array[*]}"
a,b,c

while

: (コロン)

何もしない組み込みコマンド。help にもちゃんと書いてありますね。

$ help :
:: :
    No effect; the command does nothing.  A zero exit code is returned.
無限ループ

なので、COMMANDS のところにコロンで無限ループします。

$ help while
while: while COMMANDS; do COMMANDS; done
    Expand and execute COMMANDS as long as the final command in the
    `while' COMMANDS has an exit status of zero.

echo

CR キャリッジ・リターン

キャリッジ・リターン - Wikipedia

先頭位置に移動させる

まさに復帰コード。これをつかうと先頭に戻っていることがわかります。

$ echo -e "hoge\r1"
1oge
-e オプション

shell に builtin された echo (※/bin/echo ではない)は、 -e オプションを使ってキャリッジ・リターン "¥r" などの制御文字を出力できます。

$ type echo 
echo is a shell builtin
$ help echo
echo: echo [-neE] [arg ...]
    Output the ARGs.  If -n is specified, the trailing newline is
    suppressed.  If the -e option is given, interpretation of the
    following backslash-escaped characters is turned on:
        \a  alert (bell)
        \b  backspace
        \c  suppress trailing newline
        \E  escape character
        \f  form feed
        \n  new line
        \r    carriage return
        \t  horizontal tab
        \v  vertical tab
        \\  backslash
        \0nnn   the character whose ASCII code is NNN (octal).  NNN can be
            0 to 3 octal digits
    
    You can explicitly turn off the interpretation of the above characters
    with the -E option.

無理に echo の -e オプションを使わなくても printf でもいいかもしれません。

$ printf "hoge\r1\n"
1oge
sleep 小数

他のシステムで動作する保証はありませんので、注意。

$ man sleep

The sleep command will accept and honor a non-integer number of specified seconds (with a `.' character as a decimal point). This is a non-portable extension, and its use will nearly guarantee that a shell script will not execute properly on another system.

なぜくるくるさせたかったのか

バックグラウンド実行している間にくるくるさせたかったのです。

ということで、少し書き換えてみます。

$ cat hoge.sh 
#!/bin/bash

spin() {
  local chars=('/' '-' '\' '|') i=0 mod=0

  sleep 10 &
  local pid=$!

  while kill -0 $pid >& /dev/null
  do    
    echo -ne ${chars[mod]} "\r"
    mod=$(( ++i % ${#chars[@]} ))
    sleep .1
  done
}

spin

echo done.
kill -0
$ help kill
$ man kill

しても、シグナルナンバー0のことが書いてなかったので説明飛ばします(というか知りません…)。プロセスの存在確認でよく見るパターンです。

これで無事、プロセスが存在する間くるくるできました。

We're hiring!

私たちは頑張らないエンジニアを募集しています。

www.wantedly.com

© 2016 CrowdWorks, Inc., All rights reserved.