1からNまでのmksh forループの作成方法

1からNまでのmksh forループの作成方法

だから私はこれをしようとします。

for x in {1..7000}
do
   echo $x
done

出力は次のとおりです{1..7000}

また、Cスタイルのforループがmkshでは機能しないことも学びました。

私はいくつかのインターネット検索をしましたが、ほとんどはmkshではなくkshに関する情報です。

もしそうなら、mkshで範囲を繰り返す正しい方法は何ですか?

メモ:私は文字列を印刷するよりも繰り返しとCと同様の動作を生成する正しい方法に興味があります。

ベストアンサー1

ではまず、現状のままここで簡単に議論しました一般的なフォーム...

for arg in {brace..expanded..set}; do ...

...私の考えでは、これがシェルプログラミングエラーの代表的な例です。ループから数式セットを作成し、各結果を区切り配列に保存してから次に渡します。別のループ配列を繰り返すリストとして表します。

通常、角かっこ拡張はプログラミング環境では特に有用ではありません。すべてのシェルプログラミングは何らかの方法でマクロそして支柱の拡張すでにマクロです。支柱の拡張は(私も思う)とても役に立つ対話型シェル機能はマクロなので便利です。それ以外の場合は無駄になります。

サポート拡張も移植可能ではありません。(読む:POSIX - ポータブル)。私が知っている限り、通常は現在のバージョンの、、、、zshではbash動作できますが、yash他の場所では動作しません。これらのシェルでもシェルオプションを使用して無効にすることができるため、通常はまたは出力で可用性をテストできますが、シェル機能の文脈にksh93絶対に依存することはできません。その間に上記のシェルのそれぞれには異なる種類のテストが必要ですので、これを関数に使ってテストしたい場合は、ターゲットシェルのマニュアルで具体的な内容を確認してください。$-set +o

他のシェルでは、コマンド置換の出力を分割してほぼ同じ動作を得ることができます。ただし、コレクションを作成するには外部実行可能ファイルを呼び出す必要がある点だけが異なります$IFS。これはプログラムがseq利用可能な場所で簡単に実証されています。例えば…

unset IFS       
### ^ensure $IFS default behavior
for arg in $(seq 7000)
do  printf %d\\n "$arg"
done

...または...

unset IFS
printf %d\\n $(seq 7000)

...しかし、書かれているように、どちらも欠点以外には何も提供しません...

seq 7000

ただし、最初の例では、メソッドは中括弧拡張バージョンとほぼ同じです。どちらの場合も、他のいくつかの関数またはプロセスは完全な引数リストを生成し、コントロールforコンストラクタによって繰り返されます。しかし、後者の場合、(その他のシェルのksh93場合パイプを開く/解体もあり、シェルプロセスとそのサブプロセスを分岐し、seq最後に$IFS

$IFSしかし、分割は使用されているシェルに応じて非常に異なる速度で発生します。bashたとえば、単純な$IFS分割パフォーマンスはしばしば不都合ですが、dash分割文字列の行の長さに応じて、中かっこ拡張を実行する他のシェルほど速くなる可能性があります。

ただし、中かっこ拡張を使用しても分割を使用しても、$IFS最終結果はいくつかのループを実行して数式リストを生成し、別のループを実行してそのリストを繰り返すことです。代わりに、あなたがすることができ、おそらくやるべきことは、リストを生成した式の適用に対してループを実行し、使用されたイテレータをできるだけ早く処理し、満足のいく結果を得るために各イテレーションをテストすることです。 Cではこんなことをします...

for ( x = 0; x < 10; x++ ){ ...

これは、実際に行うことができる操作に似ているか、またはでbc使用できる便利な構文形式と非常によく似ています。ksh93zshbash

for (( x=0; x<10; x++ )); do ...

しかし、これもポータブルではありません。(もう一度読む:POSIX)。代わりに、以下を移植可能に実行できます。

iterator=$(( start_value - interval ))
while [ "$(( iterator += interval ))" -le "$end_value" ]; do ...

...または...

iterator=$(( start_value - interval ))
while [ "$(( ( iterator += interval ) <= end_value ))" -ne 0 ]; do ...

POSIXの指定C算術演算(つまり、整数が含まれている場合)のシェル算術拡張と機能パリティチェックに似ています。その結果、単一の拡張で複雑な数式を便利かつ移植可能に繰り返すことができ、複数の変数を同時に同時に繰り返すこともできます。

一方、これらの構成は、他のC言語とシェル言語の不平等を解決するのが難しくなります。シェルの読み書きはほとんど常にリテラルsとs(各システムコール自体)であり、read()シェル構文には移植可能および/またはアナログはwrite()ありません。したがって、各反復でこれらのタスクを実行するループは(このタスクを実行するために組み込み関数のみを使用しても)パフォーマンスの低下を招く可能性があります。fread()fwrite()setbuf()

しかし、時にはシェルスクリプトからコレクション全体を順次または並列に構築して実行することの間で妥協を見つけることができます。

set 0 1 2 3 4 5 6 7 8 9
for n do printf "$n%d\n" "$@"; done

これはwrite()10回繰り返して10回実行され、00から99の間に改行で区切られたシーケンスを印刷します。これは非常に小さな例であり、まだ無駄です。 30バイトwrite()は3バイトに比べて大幅に改善されていないからです。write()しかし、これはあなたが利用できるこのタイプのアプローチを示しています。前述したように、シェルプログラミング言語は非常に便利です。マクロ内部にすべては文字列です。したがって、ターゲットセットをより小さく管理しやすいセットに分割し、ループコンテキストで繰り返し呼び出して最終的にターゲットセットを作成できる場合は、よりパフォーマンスの良い結果が得られることがよくあります。

以下は、より複雑でマクロに似た例です。

sh -c '
    i=0 _i=-25
    set "$1" "$1" "$1" "$1" "$1"
    for n do eval "
        printf %b%d $@ $@ $@ $@ $@"
done' -- \
    '"\01$((1+(i<(i+=!(_i=(_i+=25)%275)))))" "$i$_i"'

write()それぞれ平均約100バイトに対して5回繰り返し、次のものを印刷します。

10      125     150     175     1100    1125    1150    1175    1200    1225    1250
20      225     250     275     2100    2125    2150    2175    2200    2225    2250
30      325     350     375     3100    3125    3150    3175    3200    3225    3250
40      425     450     475     4100    4125    4150    4175    4200    4225    4250
50      525     550     575     5100    5125    5150    5175    5200    5225    5250
60      625     650     675     6100    6125    6150    6175    6200    6225    6250
70      725     750     775     7100    7125    7150    7175    7200    7225    7250
80      825     850     875     8100    8125    8150    8175    8200    8225    8250
90      925     950     975     9100    9125    9150    9175    9200    9225    9250
100     1025    1050    1075    10100   10125   10150   10175   10200   10225   10250
110     1125    1150    1175    11100   11125   11150   11175   11200   11225   11250
120     1225    1250    1275

おすすめ記事