0

カウントダウンタイマースクリプトを作成しようとしています。このスクリプトは、秒数をとっ$1てからゼロまでカウントダウンし、現在の残りの秒数を表示します。

問題は、またはがない埋め込みボックスでこれを行っていることです。これは、数値のリストを生成できることがわかっている2つのツールですseqjot

通常の(埋め込まれていない)システムで動作しているスクリプトは次のとおりです。

#!/bin/sh

for i in $(/usr/bin/jot ${1:-10} ${1:-10} 1); do
    printf "\r%s " "$i"
    sleep 1
done

echo ""

これはFreeBSDで動作します。forLinuxボックスを使用している場合は、次の行に置き換えることができます。

for i in $(/usr/bin/seq ${1:-10} -1 1); do

同じ効果のために。

jotしかし、 ORがない場合はどうすればよいseqですか?

4

3 に答える 3

5

「バニラ」ボーンシェルの問題は、そのようなものがないことです。動作は特定の実装によって異なります。最新のほとんどの/bin/shes には POSIX 機能がありますが、詳細が異なります。私は、「sh-compatibility」モードに入ると、非常に古い Bourne 機能に戻る習慣があります。これは、30 年前には役に立ちましたが、組み込みシステムであっても、最新のシステムでは通常やり過ぎです。:)

とにかく、これは非常に古いシェルでも機能する一般的なカウントダウン ループですが、最新の bash/dash/ksh/zsh/etc でも問題なく機能します。コマンドが必要ですがexpr、これはかなり安全な要件です。

i=10
while [ $i -gt 0 ]; do
  ...
  i=`expr $i - 1`
done

したがって、組み込みシステムに がある場合printf、スクリプトは次のとおりです。同じ「引数が指定されていない場合はデフォルトで 10 になります」動作:

#!/bin/sh
n=$1
i=${n-10}
while [ $i -gt 0 ]; do
  printf '\r%s ' "$i"
  i=`expr $i - 1`
  sleep 1
done

(最初の 2 行はおそらく単に に置き換えることができますi=${1-10}が、いくつかの - これも古代の - シェルは、数値パラメーターに特別なパラメーター展開を適用することを好みませんでした。)

システムに がない場合、printf問題が発生します。シェルのビルトインのみecho(またはビルトインなしでランダムに選択された の実装/bin/echo)では、これらのいずれかを行う保証された方法はありません(特殊文字をエコーするか、改行を防止します)。キャリッジ リターンを使用\rまたは取得できる場合があります。\015それらをシェルに認識させる必要-eがあるかもしれません(しかし、それはリテラルをエコーするだけかもしれません-e)。スクリプト内にリテラル キャリッジ リターンを配置するとおそらく機能しますが、スクリプトの維持が面倒になります。

同様に-n、改行を押しつぶす可能性がありますが、リテラルを単にエコーする可能性があります-n。改行を押しつぶす最も初期の方法は、改行が自然に移動するecho特別なシーケンスを使用していました。これは、 (Mac OS X のバージョンを含む) の一部のバージョンで、または bash の組み込みの echo オプションと組み合わせて\c引き続き機能します。/bin/echo-e

したがって、スクリプトの最も単純な部分のように見える部分は、awk.

于 2013-01-13T04:43:06.260 に答える
0

Bash を使用している場合は、次のようにします。

for i in {1..10}

それともバッシュなし?この投稿の内容はどうですか?Bourne Shell For i in (seq)

試す

for i in 1 10 15 20
do
   echo "do something with $i"
done

それ以外の場合、最近の Solaris を使用している場合は、少なくとも bash 3 があります。たとえば、これは1から10および15から20の範囲を与えます

for i in {1..10} {15..20}
do
  echo "$i"
done

または nawk のようなツールを使用する

for i in `nawk 'BEGIN{ for(i=1;i<=10;i++) print i}'`
do
  echo $i
done

または while ループでも

while [ "$s" -lt 10 ]; do s=`echo $s+1|bc`; echo $s; done
于 2013-01-13T04:39:34.690 に答える
0

シェルが bash の場合、次のように固定数からカウントダウンできます。

#!/bin/bash

for n in {10..1}; do
  printf "\r%s " $n
  sleep 1
done

しかし、それはうまくいきません。bash は のようなものを処理せず{${1:-10}..1}、コマンド ライン オプションが必要だと指定したからです。もちろん、あなたは bash を使用していないとも言っているので、より単純なシェルを想定します。

があればawk、それを使って数えることができます。

#!/bin/sh

for n in $(awk -v m="${1:-10}" 'BEGIN{for(;m;m--){print m}}'); do
  printf "\r%s " $n
  sleep 1
done
printf "\r \r"  # clean up

awk がない場合は、純粋なシェルで実行できるはずです。

#!/bin/sh

n=${1:-10}

while [ $n -gt 0 ]; do
  printf "\r%s " $n
  sleep 1
  n=$((n-1))
done
printf "\r \r"  # clean up

純粋なシェル バージョンは、おそらく awk ソリューションよりも優先されるほど単純であると思います。

もちろん、Mark Reed がコメントで指摘したように、システムに が含まれていない場合は、OS またはシェルに依存するprintf醜い魔法を実行する必要があります...そして、シェルが をサポートしていない場合は、その行を に置き換えることができます。数値以外が提供された場合に備えてエラー処理を追加したい場合は、問題はありません。echo$((..))n=$(expr $n - 1)$1

于 2013-01-13T04:46:09.073 に答える