POSIXシェルスクリプトで算術ループを作成するにはどうすればよいですか?


12

で算術forループを作成する方法を知っていますbash

POSIXシェルスクリプトで同等のループを実行するにはどうすればよいですか?

同じ目標を達成するにはさまざまな方法があるため、自由に独自の答えを追加し、それがどのように機能するかを少し詳しく説明してください。

このようなbashループの例を次に示します。

#!/bin/bash
for (( i=1; i != 10; i++ ))
do
    echo "$i"
done

@StéphaneChazelasこれは、OPがbashであることを示唆していないため、単にbashを例として使用しているため、誤解に基づいているように思われる履歴に関するメモでした。それは本当に関連しているようには見えませんでした。
terdon

回答:


13

Shellcheck.net wikiで役立つ情報を見つけました。引用します。

  1. バッシュ:

    for ((init; test; next)); do foo; done
  2. POSIX:

    : "$((init))"
    while [ "$((test))" -ne 0 ]; do foo; : "$((next))"; done

ただし、i++POSIX ではないため、たとえばi += 1またはに変換する必要があることに注意してくださいi = i + 1


したがって、上記の質問のスクリプトは、次のようなルールを使用してPOSIXごとに書き直すことができます。

#!/bin/sh
: "$((i=1))"
while [ "$((i != 0))" -ne 0 ]
do
    echo "$i"
    : "$((i = i + 1))"
done

ここでも、次のようにすると読みやすくなります。

#!/bin/sh
i=1
while [ "$i" -ne 10 ]
do
    echo "$i"
    i=$((i + 1))
done

のようにinit、定数値を割り当てているため、算術式を評価する必要はありません。i != 10中には、test簡単に翻訳することができます[表現、およびためnext、シェル変数の代入を使用して算術式内の変数の代入とは反対に、私たちは取り除くことができます:し、引用の必要性。


横にi++- > i = i + 1、あなたがしなければならないかもしれないというPOSIXではないのksh / bashの固有の構築物の複数の翻訳があります。

  • i=1, j=2算術演算子はないが、実際に POSIX(とは、ksh93といくつかのロケールの小数点セパレータと競合)。あなたは次のように別のオペレータでそれを置き換えることができますのようにしかし使用して、より多くの読みやすくなります。,+: "$(((i=1) + (j=2)))"i=1 j=2
  • a[0]=1:POSIXシェルには配列がありません
  • i = 2**20:POSIXシェル構文にパワー演算子がありません。<<はサポートされていますが、2の累乗の場合、1つを使用できますi = 1 << 20。他の権限については、次の手段をとることができますbci=$(echo "3 ^ 20" | bc)
  • i = RANDOM % 3:POSIXではありません。POSIXツールチェストで最も近いのはi=$(awk 'BEGIN{srand(); print int(rand() * 3)}')です。

2

上記の違いに関する詳細な背景知識に感謝します。shellcheck.netを使用しているときに機能する代替品のドロップは、次のとおりです。

バッシュ

for i in {1..100}; do  
  ...  
done  

POSIX

i=0; while [ $i -le 100 ]; do  
  ...  
  i=$(( i + 1 ))  
done

seqはseq 1 10を使用するオプションでもあると指摘する人もいます。ループを作成しますが、これはosがseqを持っているかどうかに依存します。


iをwhileと同じ行に配置したことに注意してください。読みやすさは良くありませんが、ワンライナーのドロップインです。これにより、スクリプトで定義されている他の場所によって変数iが汚染されることがなくなります。
ジミーMGリム
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.