私のPIDリストからPIDが削除されない理由を説明できる人はいますか?このループに入るたびに、forループはまだ同じ回数で発生します。 var i は pid 数と同じです。したがって、すべてのpidが完了したら、whileループを停止する必要がありますが、そうではありません!まだpids配列にpidがあります。
このコマンドはうまくいかないようです:pids =(" $ {pids [@] / $ pid}")何か問題がありますか? pids配列から$ pidを削除したいです。
while [ $i != 0 ]
do
for pid in "${pids[@]}"
do
if [ -z "$(ps -p $pid -o pid=)" ]
then
echo "i = $i ,pid $pid is finished" | tee -a $LOGFILE
((i--))
pids=("${pids[@]/$pid}")
echo
else
echo "i = $i ,pid $pid is not finished"
fi
done
sleep 4
clear
done
答え1
問題は、これは配列の項目が空の文字列( "")で置き換えられること("${pids[@]/$pid}")
です。$pid
したがって、このプロジェクトは実際には削除済み配列ではそれだけ交換済み空の文字列エントリがあります。
私はいくつかのpidが配列から「削除」された後、次のサイクルで次の行がエラーを生成for pid in "${pids[@]}"
すると思います。一部$pid 変数は空です。
if [ -z "$(ps -p $pid -o pid=)" ]
これはps
stderrにいくつかのエラーを引き起こす可能性がありますが、コマンド(STDOUT)の出力は空であるため、1ずつ減少して$i
最終$i
的に0を下回る可能性があり、決してゼロにならないため、ループは停止しません。
配列内のすべての項目は数値なので、次の行から引用符を削除することでこの問題を解決できます。
pids=("${pids[@]/$pid}")
したがって、次のようになります。
pids=(${pids[@]/$pid})
引用符がない場合は、空の要素が配列から削除されます。
以下は簡単な例です。
$ array=( 1 2 3 )
$ echo "${array[@]/1}"
2 3
# Notice that the first item is replaced with an empty string
$ echo ${array[@]/1}
2 3
# Without the quotes, the empty string is removed
これは、配列内の項目が数値なので機能することに注意してください。配列に文字列とスペースが含まれている場合は機能しません。
また、この方法はサブストリング(たとえば、完全な配列項目である必要はありません)、たとえば、pids=( "1", "123" )
およびの場合、pid=1
結果(${pids[@]/1})
は( "23" )
「123」から「1」を削除し、「23」のみを残します。
下記をご覧ください回答配列の内容に関係なく、すべての配列からアイテムを削除する方法と詳細を学びます。
婦人声明:
この答えは、スクリプトが期待どおりに機能しない理由だけを説明します。私の提案はスクリプトがうまくいくかもしれませんが、最も最適化された方法で書かれていませんでした。スクリプトをよりきれいで効率的にするための多くの変更点がありますが、この回答ではこれに対処しません。