ウェブサイト検索

「数字を推測する」ゲームをコーディングして awk を学習する


プログラミング言語には多くの共通の特徴がある傾向があります。新しい言語を学習するための優れた方法の 1 つは、使い慣れたプログラムを作成することです。この記事では、よく知られた概念を示すために、awk を使用して「数字を推測する」ゲームを作成します。

新しいプログラミング言語を学ぶときは、ほとんどのプログラミング言語に共通する次のことに焦点を当てるのが良いでしょう。

  • 変数 – 情報が保存される場所
  • 式 – 物事を計算する方法
  • ステートメント - プログラム内で状態変化を表現する手段

これらの概念は、ほとんどのプログラミング言語の基礎です。

これらの概念を理解したら、残りの部分を理解し始めることができます。たとえば、ほとんどの言語には、その設計によってサポートされる「物事を行う方法」があり、それらの方法はプログラムごとにまったく異なる場合があります。これらの方法には、モジュール性 (関連する機能をグループ化する)、宣言型と命令型、オブジェクト指向、低レベルと高レベルの構文機能などが含まれます。多くのプログラマーにとって馴染みのある例は、「儀式」、つまり、問題に取り組む前に状況を設定するために必要な作業量です。 Java プログラミング言語には、その設計に起因する重要な儀式要件があると言われており、すべてのコードをクラス内で定義する必要があります。

しかし、基本に立ち返ってください。通常、プログラミング言語には類似点があります。 1 つのプログラミング言語を理解したら、その新しい言語の違いを理解するために、別のプログラミング言語の基本を学ぶことから始めます。

続行するための良い方法は、基本的なテスト プログラムのセットを作成することです。これらを手に入れて、学習はこれらの類似点から始まります。

使用できるテスト プログラムの 1 つは、「数字を推測する」プログラムです。コンピューターは 1 から 100 までの数字を選択し、その数字を推測するよう求めます。プログラムは、正しい推測ができるまでループします。

「数字を推測する」プログラムは、プログラミング言語のいくつかの概念を実行します。

  • 変数
  • 入力
  • 出力
  • 条件付き評価
  • ループ

これは、新しいプログラミング言語を学ぶための素晴らしい実践的な実験です。

注: この記事は、Julia でのこのアプローチの使用に関する Moshe Zadka の記事と、Bash での実行に関する Jim Hall の記事を基にしています。

awk の数字を推測します

「数字を当てる」ゲームを Awk プログラムとして書いてみましょう。

Awk は動的に型指定され、データ変換を重視したスクリプト言語であり、対話型の使用に対する驚くほど優れたサポートを備えています。 Awk は 1970 年代から存在しており、元々は Unix オペレーティング システムの一部として使用されていました。 Awk を知らなくてもスプレッドシートが好きなら、これはサインです…Awk を学びましょう!

「数字を推測する」ゲームのバージョンを作成することから、Awk の探索を始めることができます。

私の実装は次のとおりです (特定の機能のいくつかを確認できるように行番号が付いています)。

     1    BEGIN {
     2        srand(42)
     3        randomNumber = int(rand() * 100) + 1
     4        print "random number is",randomNumber
     5        printf "guess a number between 1 and 100\n"
     6    }
     7    {
     8        guess = int($0)
     9        if (guess < randomNumber) {
    10            printf "too low, try again:"
    11        } else if (guess > randomNumber) {
    12            printf "too high, try again:"
    13        } else {
    14            printf "that's right\n"
    15            exit
    16        }
    17    }

Awk の制御構造と C または Java の制御構造との類似点はすぐにわかりますが、Python とは異なります。 if-then-else や while などのステートメントでは、then、else、および while 部分は、{ と } で囲まれた 1 つのステートメントまたはステートメントのグループを受け取ります。ただし、AWk には最初から理解しておく必要がある大きな違いが 1 つあります。

設計上、Awk はデータ パイプラインを中心に構築されています。

それはどういう意味ですか?ほとんどの Awk プログラムは、入力行を受け取り、そのデータに対して何らかの処理を行って、それを出力に書き込むコードの断片です。このような変換パイプラインの必要性を認識し、Awk はデフォルトですべての変換配管を提供します。上記のプログラムを通じて、「コンソールからデータを読み取る」構造はどこにあるのかという基本的な質問をして、それを調べてみましょう。

その答えは、それは組み込まれているということです。特に、7 行目から 17 行目は、読み取られた各行をどう処理するかを Awk に指示します。このコンテキストを考慮すると、何かが読み取られる前に 1 ~ 6 行目が実行されることが非常に簡単にわかります。

より具体的には、1 行目の BEGIN キーワードは一種の「パターン」であり、この場合、データを読み取る前に BEGIN に続く内容を実行する必要があることを Awk に示します。 > { … } 内。同様の END キーワードは、このプログラムでは使用されていませんが、すべてが読み取られたときに何をすべきかを Awk に示します。

7 ~ 17 行目に戻ると、同様のコード ブロック { … } が作成されていることがわかりますが、先頭にキーワードがありません。 Awk では { の前に一致するものがないため、受信した入力のすべての行にこの行が適用されます。入力の各行は、ユーザーの推測に従って入力されます。

実行されるコードを見てみましょう。まず、入力が読み取られる前に発生するプリアンブルです。

2 行目では、乱数ジェネレーターを数値 42 で初期化します (引数を指定しない場合は、システム クロックが使用されます)。 42?もちろん 42 です。 3 行目は 1 から 100 までの乱数を計算し、4 行目はデバッグ目的でその数値を出力します。 5 行目は、ユーザーに数字を推測するよう促します。この行では、print ではなく printf を使用していることに注意してください。 C と同様、printf の の最初の引数は、出力のフォーマットに使用されるテンプレートです。

ユーザーは、プログラムが入力を期待していることを認識したので、コンソールに推測を入力できます。前述したように、awk はこの推測をコードの 7 ~ 17 行目に提供します。 18 行目では、入力レコードを整数に変換します。 $0 は入力レコード全体を示し、$1 は入力レコードの最初のフィールド < を示します。 2 番目はstrong>$2、というように続きます。そうです、Awk は、事前定義された区切り文字 (デフォルトは空白) を使用して、入力行を構成フィールドに分割します。 9 ~ 15 行目では、推測と乱数を比較し、適切な応答を出力します。推測が正しければ、行 15 は入力行処理パイプラインから途中で終了します。

単純!

特定の入力行設定に反応してデータを操作するコード スニペットとしての Awk プログラムの珍しい構造を考慮して、フィルタリング部分がどのように機能するかを確認するためだけに別の構造を見てみましょう。

     1    BEGIN {
     2        srand(42)
     3        randomNumber = int(rand() * 100) + 1
     4        print "random number is",randomNumber
     5        printf "guess a number between 1 and 100\n"
     6    }
     7    int($0) < randomNumber {
     8        printf "too low, try again: "
     9    }
    10    int($0) > randomNumber {
    11        printf "too high, try again: "
    12    }
    13    int($0) == randomNumber {
    14        printf "that's right\n"
    15        exit
    16    }

1行目から6行目までは変更されていません。しかし、行 7 ~ 9 は行の整数値が乱数より小さい場合に実行されるコードであり、行 10 ~ 12 は行の整数値が乱数より大きい場合に実行されるコードであることがわかります。 、13 ~ 16 行目は、2 つが一致した場合に実行されるコードです。

これは「クールだけど奇妙」に見えるはずです。たとえば、なぜ繰り返し int($0) を計算するのでしょうか?そして確かに、それは問題を解決する奇妙な方法になるでしょう。しかし、これらのパターンは、正規表現や Awk でサポートされているその他の構造を使用できるため、条件付き処理を分離する非常に素晴らしい方法となります。

完全を期すために、これらのパターンを使用して、一般的な計算を特定の状況にのみ適用されるものから分離することができます。以下に 3 番目のバージョンを示します。

     1    BEGIN {
     2        srand(42)
     3        randomNumber = int(rand() * 100) + 1
     4        print "random number is",randomNumber
     5        printf "guess a number between 1 and 100\n"
     6    }
     7    {
     8        guess = int($0)
     9    }
    10    guess < randomNumber {
    11        printf "too low, try again: "
    12    }
    13    guess > randomNumber {
    14        printf "too high, try again: "
    15    }
    16    guess == randomNumber {
    17        printf "that's right\n"
    18        exit
    19    }

どのような入力値が入ってきたとしても、それを整数に変換する必要があることを認識し、それを行うために 7 ~ 9 行目を作成しました。 3 つの行グループ、10 ~ 12、13 ~ 15、および 16 ~ 19 は、毎回入力行を変換するのではなく、すでに定義された変数推測を参照するようになりました。

学びたいことのリストに戻りましょう。

  • 変数 – はい、Awk には変数があります。入力データは文字列として入力されますが、必要に応じて数値に変換できると推測できます。
  • input – Awk は、内容を読み取るための「データ変換パイプライン」アプローチを通じて入力を送信するだけです
  • 出力 – Awk の print および printf プロシージャを使用して、出力に内容を書き込みました。
  • 条件評価 – Awk のif-then-else と、特定の入力ライン構成に応答する入力フィルターについて学習しました。
  • ループ – え、想像してみてください!ここでも、Awk が採用している「データ変換パイプライン」アプローチのおかげで、ループは必要ありませんでした。ループは「ただ起こる」のです。ユーザーはファイル終了シグナルを Awk に送信することでパイプラインを途中で終了できることに注意してください (Linux ターミナル ウィンドウを使用する場合はCTRL-D)。

入力を処理するループが不要であることの重要性を考慮する価値は十分にあります。 Awk がこれほど長い間存続し続けている理由の 1 つは、Awk プログラムがコンパクトであることです。コンパクトな理由の 1 つは、コンソールやファイルから読み取るための定型文が必要ないことです。

プログラムを実行してみましょう:

$ awk -f guess.awk
random number is 25
guess a number between 1 and 100: 50
too high, try again: 30
too high, try again: 10
too low, try again: 25
that's right
$

取り上げていない点の 1 つはコメントです。 Awk コメントは # で始まり、行末で終わります。

まとめ

Awk は信じられないほど強力なので、この「数字を当てる」ゲームは始めるのに最適な方法です。しかし、これで旅が終わるはずはありません。 Awk と Gawk (GNU Awk) の歴史について読むことができます。Awk の拡張バージョンであり、Linux を実行している場合はおそらくコンピューターにインストールされているものです。または、初期開発者によるオリジナルについてのすべてを読むことができます。

また、チートシートをダウンロードして、学んだことすべてを追跡することもできます。

関連記事: