ループする方法、別名、反復作業を行うプログラムの設計
ループは、選択したアイテムのリストに対して、コマンドのセットを必要な回数だけ繰り返すことができるため、コンピューティングにおける最も基本的で強力な構造の1つです。計算上の考え方の多くは、1つのタスクを取得し、他のすべての同様のタスクに繰り返し適用できる方法でそれを解決することを含みます。forループは、コンピューターにその反復作業を実行させる方法です。
これまでインタラクティブプロンプトで記述したほとんどのコードとは異なり、Enterキーを押すとすぐにforループは実行されません。
do
キーワードとdone
キーワードの間のブロックに必要な数のコマンドを書き出すことができます:
done
に到達し、Enterキーを押すまでのみ、forループが機能します。
これは、プロンプトでこれまでに経験した行ごとのコマンドと応答とは根本的に異なります。また、次のコマンドの実行をあまり重視せずに、プログラミングをさらに進める方法を示しています。各行、およびプログラムの機能を計画し、後で実行することに重点を置きます。
基本的な構文
for
ループの構文は混乱を招く可能性があるため、理解を準備/更新するための基本的な例をいくつか示します。
変数を使用したより複雑なバージョン:
コマンド置換を使用して生成できますfor
ループが繰り返す項目:
から行のリストを読み取る必要がある場合ファイルであり、どの行にもスペースが含まれていないことを絶対に確認してください。
read-whileループは上記のバリエーションですが、ファイルから行を読み取る方が安全:
基本的なforループの構築
最初から始めましょう。最小限のfor
ループを作成し、それをより複雑なものに組み込んで、目的を理解できるようにします。
最も単純なループ
これはほぼ同じくらい簡単ですforループを作成できるように:
それはかなり価値がないように見えましたか?はい、あるべきです。 echo "Hi"
という1行で実行する4行のコードを記述しました。
コレクション内のその他の要素
It 「わかりにくいですが、「ループ」は実行されました。一度だけ実行されました。では、どうすれば複数回実行できますか?in
キーワード。さらに4つの1
を追加しましょう:
OK、それほどエキサイティングではありませんが、プログラムは間違いなく少なくともループしているように見えました。4つの1
“により、4つのecho
コマンドが実行されました。
これらの4つの1
“を異なる番号に置き換えるとどうなりますか?そしておそらくいくつかの単語ですか?
そして…何もありません。したがって、ループは、指定した値のコレクションに固有のことを自動的に実行しません。まだとにかく。
ループ変数を参照してください
in
キーワードの左側を見てみましょう、そしてそのx
。そのx
のポイントは何ですか?小文字のx
は、これまでに遭遇したキーワードまたはコマンドの名前ではありません(プロンプトで単独で実行すると、エラーがスローされます)。それで、多分それは変数ですか?echo
ステートメントでそれを参照してみましょう:
ビンゴ。これは、for
ループの基本的な動作のほとんどです。-アイテム/値のコレクションを取得します(Q Zebra 999 Smithsonian
)-それらをに渡しますfor
ループ構造-ループ変数(x
)をプレースホルダーとして使用して、do
/ done
ブロック。-ループが実行されると、ループ変数x
は、の各項目の値を取ります。リスト– Q
、Zebra
、999
、Smithsonian
、–およびdo
とdone
の間のコマンドブロックが実行されます。このシーケンスは、リスト内のすべてのアイテムに対して1回繰り返されます。
do
/ done
ブロックには、次の任意のシーケンスを含めることができます。コマンド、さらに別のfor
ループ:
Loops-within-loopsは、プログラミングの一般的な構成要素です。デバッグ中にねじれを解くのは難しい場合があるため、ほとんどの場合、この種のロジックに関連する問題の割り当てを回避しようとしています。
ファイルを1行ずつ読み取り、 read-whileで確実に
cat
はファイルを1行ずつ出力するため、次のforループが適切と思われます。
ただし、コマンド置換により、cat
は単語をスペースで分割します。list-of-dirs.txt
に次のようになります:
for
ループの出力は次のようになります:
read-whileループは、行内の単語を保持します:
結果からパイプすることもできます<(
および)
でコマンドを囲むことによるコマンドの例:
パイプとループ
他の言語を使用している場合、データストリームに慣れていない可能性があります。 。少なくとも、それらを操作するための構文は、RubyやPythonよりもBashの方がはるかに直接的で単純なので、私にとってはそうです。
ただし、任意の言語でのプログラミングに慣れていない場合は、また、データストリームの操作とループの操作の違いも不明です。
たとえば、次のスニペット:
–このループと同じ出力を生成します。
そして、物事のメンタルモデルによっては、両方の例で、各単語、たとえばhello
、world
は、変換プロセスを通過し(tr
を介して)、エコーされます。
パイプとフィルター
ここではパイプがループとは根本的に異なる動作をするUnixシステムの基本に立ち入ることなく、精神的な回避策を提案させてください。
stdinおよびstdoutからパイプするプログラムは、通常、データのストリームが含まれるフィルターとして配置できます。プログラムに入り、別の形式で出力されます。
フィルターからフィルターへのデータの変換以上のタスクの場合は、ループの使用を検討してください。タスクのようなものは何でしょうか? URLのリストを指定して、それぞれをダウンロードし、ダウンロードしたデータをカスタマイズした本文と件名で電子メールで送信します。
データ入力ソース、urls.txt
の各URLここでは実際にはフィルタリングされていません。代わりに、URLごとにマルチステップタスクが実行されています。
read-whileへのパイプ
とはいえ、ループ自体を実装できます。フィルタ間のもう1つのフィルタとして。echo | grep
の結果が1行ずつループ。echo
を使用してstdoutに出力され、some.txtという名前のファイルにリダイレクトされます。
これは、たとえあったとしても頻繁に行う必要のある構造ではありませんが、Unixでのパイプの使用を強化することを願っています。
インタラクティブなプログラミングが少ない
for
ループや同様の構造を頻繁に使用するということは、cの1行を入力する「古き良き時代を過ぎて」いることを意味します。エンターキーを押した直後に実行します。 for
ループ内にいくつのコマンドをパックしても、done
キーワードを押すまで何も起こりません。
一度書いてください。次に、ループします
シェルとの行ごとの相互作用が失われると、インタラクティブプロンプトの主な利点である即時フィードバックが失われます。また、まだすべての欠点があります。do
とdone
の間のコマンドブロックの早い段階でタイプミスをした場合は、開始する必要があります。
これを軽減する方法は次のとおりです。
コードを一度に1ケースずつテストします
初心者が犯す最大の過ちの1つfor
ループは、for
ループが問題をすぐに解決すると考えているため、10,000個のURLをダウンロードするだけで、 1つのURLだけを適切にダウンロードできないため、欠陥のあるコマンドをfor
ループに入れることは正しい方向への第一歩だと彼らは考えています。
これは基本的に、 for
ループの誤解ですが、実際の問題は、壊れたコードを10,000回実行していることです。つまり、コードが次のようになっていることを確認するには、10,000倍待つ必要があります。残念ながら、まだ壊れています。
だから、「for
ループ。 10,000個のURLをすべて、一度に1つのコマンドでダウンロードする必要があると仮定します。最初のURLに対してそれを行うコマンドを記述できますか。 2番目はどうですか?マイナーな構文エラーが発生していないことをある程度確信できたら、9,997個の他のURLの一般的なパターンを見つける方法を検討します。
スクリプトを作成する
インタラクティブなコマンドラインは素晴らしいです。最初は楽しかったし、コンピューティングのキャリア全体を通して楽しそうです。しかし、10行を超えるコードを含む大きなタスクが目の前にある場合は、そのコードをシェルスクリプト。間違いのない人間の指がコードを完璧に再入力することを信用しないでください。
nanoを使用してループを処理し、シェルとして保存しますスクリプト。長いファイルの場合は、「コンピューターのテキストエディター(Sublime Text)で作業してから、サーバーにアップロードします。
Webスクレイピングを使用して練習します
forループの構文と動作については、次のようになります。ルーチンタスクをループに変換するまでの思考プロセス:
1から10までの数字の場合curlを使用して、各番号のWikipediaエントリをダウンロードし、「
wiki-number-(whatever the number is).html
」
昔ながらの方法
10個のURLだけで、いくつかの変数を設定してから、curlコマンドを10回コピーアンドペーストして、各行に変更を加えることができます。
そして何を推測しますか?できます。 10個のURLの場合、これは悪い解決策ではなく、昔ながらの方法(Webブラウザーから実行)よりも大幅に高速です。
繰り返しを減らす
ループについて考えなくても、変数を使用して繰り返しを減らすことができます。ベースURL、、およびベースファイル名は変更されないため、これらの値を変数に割り当てましょう。再利用できます:
forループの適用
この時点で、パターンを単純化して、個別のタスクごとにほとんど変化がないことを確認しました。 for
ループについて学習した後、あまり考えずに適用できます(Webリクエスト間で一時停止するようにsleepコマンドも追加します)
生成リスト
ほとんどの場合、forループの作成は簡単です。それは大変な作業になる可能性のあるリストの作成です。1から100までのページを収集したい場合はどうでしょうか?それは「多くの入力です。
しかし、怠惰に指示させれば私たちの考えでは、xからyまでのカウントは、本質的に計算タスクのように見えると想像できます。そして、Unixにはこのためのseq
ユーティリティがあります。
反復用の非数値のリストの生成
多くの反復タスクxからyまで数えるほど単純ではないので、問題はアイテムの非線形リストを生成する方法になりますか?これは基本的にデータ収集と管理の技術です。しかし、簡単なシナリオを作成しましょう。私たち自身:
現在のNYTimes.comフロントページの見出しに少なくとも1回表示される10文字(またはそれ以上)の単語のうちの10個についてその単語のWiktionaryページを取得します
このタスクを2つの部分に分割します。
- 10個のリストを取得します10 + -nytimes.comの見出しからの文字の単語
- それらの単語をforループに渡す
ステップ1:pupユーティリティ(またはコマンドラインのHTMLパーサー選択):
ステップ2(words
変数が渡されていると仮定):
SoftwaをチェックしてくださいreCarpentryのBashのforループに関する優れたガイド