私はbashスクリプトを学んでいますが、スクリプトで作業している間にスピナーを自分で作成しようとしている間にこのコードを見つけました。この問題:
i=1
sp="/-\|"
echo -n ' '
while true
do
printf "\b${sp:i++%${#sp}:1}"
done
これが私が探していたものです。接続せずにアイテムを削除し、次の文字をエコーするスピナーの種類。$sp
しかし、私はこれがどのように機能するのか理解していません
printf "\b${sp:i++%${#sp}:1}"
誰かが私のためにこれを詳しく説明して、何が起こっているのか理解できますか?プログラミングの観点から見ると、三項forループのように見えますが、sp:i++
その後は迷子になります。 1はvarに1つの文字しか表示しないことを意味しています$sp
。
私はこれが決してwhile
終わらないことを知っています。
私が試した結果が同じ結果を提供していないため、いくつかの違いがあることにもecho
注目する価値があります。printf
echo
echo "\b${sp:i++%${#sp}:1}"
引用する
答え1
これには2つの変数があります。何が起こっているのかをよりよく見ることができます。
sp="abcd" i=0 # Initialisation
printf "%d %s %d\n" "$i" "${sp:i++%${#sp}:1}" "$i" # Repeat this line a few times
ご覧のとおり、式が使用されるたびに$i
1ずつ増加します()。$i++
の長さをモジュール化し、$sp
文字列の先頭インデックスとして使用します$sp
。したがって$i
、isの6
場合、3番目の文字が印刷さ6 % 4
れます(文字列オフセットは0から始まります)。2
$sp
次の表現を解くことができます。
sp="abcd" i=0
len_sp=${#sp} # length of $sp
i=$(( i + 1 )) # increment $i
mod_i=$(( i % len_sp )) # wrap around length of $sp
sp_sub=${sp:mod_i:1} # get substring of one character
printf "%s" "$sp_sub" # print it
もう一つの興味深い部分は、echo -n ' '
末尾の改行なしでスペースを印刷し、printf "\b"
バックスペースキーを印刷することです。
答え2
echoはまったく賢いことをしません。 2文字だけをエコーします。
\b
バックスペースキーです。これにより、画面に1つの列が返されます。見える文字は変数spの4文字のうちの1つです。その後、画面上の1つの前に移動します。だから絶えずキャラクターをお互いより優先させます。だから
/
-
\
|
順番に視聴してください。
内部には、${ .... }
indexを使用して4文字を繰り返すシェル拡張がありますi
。
${sp:i:1}
の内容から位置にある文字を選択する部分文字列拡張を使用して文字を選択します。i
$sp
この
i++
セクションはi
使用されるたびに増加してから1文字を移動しますsp
。%
の終わりまで実行されたときに「最初に戻る必要がある」モジュロ操作です。i
sp
${#sp}
長さを返すシェル拡張ですsp
。
このトリックでは、回転速度を遅くするためにループ内の遅延(たとえば、スリープ0.25)が必要です。
待っているすべてのタスクが完了したことを検出する必要があります。このシェルが非同期プロセスを開始すると、「タスク」を実行し、サブプロセスがないことを確認できます。ファイルが生成されるのを待っている場合は、それをテストできます。