GNU/Linux >> Linux の 問題 >  >> Linux

2つの簡単なチュートリアルでawkスキルを向上させます

Awkは、UnixおよびLinuxユーザーのツールボックスで最も古いツールの1つです。 1970年代にAlfredAho、Peter Weinberger、およびBrian Kernighan(ツール名のA、W、およびK)によって作成されたawkは、テキストストリームの複雑な処理のために作成されました。これは、テキストファイルの行ごとの処理用に設計されたストリームエディタであるsedのコンパニオンツールです。 Awkは、より複雑な構造化プログラムを可能にし、完全なプログラミング言語です。

この記事では、単純なメールマージアプリケーションなど、より構造化された複雑なタスクにawkを使用する方法について説明します。

Awkプログラム構造

awkスクリプトは、 {}で囲まれた機能ブロックで構成されています (中括弧)。 BEGINという2つの特別な機能ブロックがあります。 およびEND 、入力ストリームの最初の行を処理する前、および最後の行が処理された後に実行されます。その間のブロックの形式は次のとおりです。

pattern { action statements }

各ブロックは、入力バッファの行がパターンと一致したときに実行されます。パターンが含まれていない場合、機能ブロックは入力ストリームのすべての行で実行されます。

また、次の構文を使用して、任意のブロックから呼び出すことができるawkの関数を定義できます。

function name(parameter list) { statements }

このパターンマッチングブロックと関数の組み合わせにより、開発者は再利用と読みやすさのためにawkプログラムを構築できます。

awkがテキストストリームを処理する方法

Awkは、入力ファイルからテキストを読み取るか、一度に1行ずつストリーミングし、フィールド区切り文字を使用してテキストを複数のフィールドに解析します。 awkの用語では、現在のバッファーはレコードです。 。 awkがファイルを読み取って処理する方法に影響を与えるいくつかの特別な変数があります:

  • FS (フィールド区切り文字):デフォルトでは、これは任意の空白(スペースまたはタブ)です
  • RS (レコード区切り文字):デフォルトでは、改行( \ n
  • NF (フィールド数):awkが行を解析するとき、この変数は解析されたフィールドの数に設定されます
  • $ 0: 現在の記録
  • $ 1、$ 2、$ 3など: 現在のレコードの1番目、2番目、3番目などのフィールド
  • NR (レコード数):awkスクリプトによってこれまでに解析されたレコード数

awkの動作に影響を与える変数は他にもたくさんありますが、最初はこれで十分です。

Awkワンライナー

非常に強力なツールの場合、awkの使用法のほとんどが基本的なワンライナーであるのは興味深いことです。おそらく、最も一般的なawkプログラムは、CSVファイルやログファイルなどの入力行から選択したフィールドを出力します。たとえば、次のワンライナーは、 / etc / passwdからのユーザー名のリストを出力します。 :

awk -F":" '{print $1 }' /etc/passwd

上記のように、 $ 1 現在のレコードの最初のフィールドです。 -F オプションは、FS変数を文字に設定します 。

フィールドセパレータは、BEGIN機能ブロックで設定することもできます:

awk 'BEGIN { FS=":" } {print $1 }' /etc/passwd

次の例では、シェルが / sbin / nologinではないすべてのユーザー ブロックの前にパターンマッチを付けることで印刷できます:

awk 'BEGIN { FS=":" } ! /\/sbin\/nologin/ {print $1 }' /etc/passwd

高度なawk:メールマージ

いくつかの基本事項がわかったので、より構造化された例でawkを深く掘り下げてみてください:メールマージの作成。

メールのマージでは、2つのファイルが使用されます。1つは(この例では email_template.txt と呼ばれます) )送信するメールのテンプレートが含まれている:

From: Program committee <[email protected]>
To: {firstname} {lastname} <{email}>
Subject: Your presentation proposal

Dear {firstname},

Thank you for your presentation proposal:
  {title}

We are pleased to inform you that your proposal has been successful! We
will contact you shortly with further information about the event
schedule.

Thank you,
The Program Committee

もう1つはCSVファイル( proposals.csv と呼ばれます)です。 )メールを送信する相手と:

firstname,lastname,email,title
Harry,Potter,[email protected],"Defeating your nemesis in 3 easy steps"
Jack,Reacher,[email protected],"Hand-to-hand combat for beginners"
Mickey,Mouse,[email protected],"Surviving public speaking with a squeaky voice"
Santa,Claus,[email protected],"Efficient list-making"

CSVファイルを読み取り、最初のファイルの関連フィールドを置き換え(最初の行をスキップ)、結果を acceptanceN.txtというファイルに書き込みます。 、 Nをインクリメント 解析する行ごとに。

mail_merge.awkというファイルにawkプログラムを記述します 。ステートメントは;で区切られます awkスクリプトで。最初のタスクは、フィールドセパレータ変数とスクリプトに必要な他のいくつかの変数を設定することです。また、CSVの最初の行を読み取って破棄する必要があります。そうしないと、親愛なる名で始まるファイルが作成されます。 。これを行うには、特殊関数 getlineを使用します 読み取り後にレコードカウンタを0にリセットします。

BEGIN {
  FS=",";
  template="email_template.txt";
  output="acceptance";
  getline;
  NR=0;
}

主な機能は非常に単純です。処理される行ごとに、さまざまなフィールド()に変数が設定されます。 、メール 、およびタイトル 。テンプレートファイルは1行ずつ読み取られ、関数は sub 特殊文字シーケンスの出現を関連する変数の値で置き換えるために使用されます。次に、置換が行われた行が出力ファイルに出力されます。

テンプレートファイルと行ごとに異なる出力ファイルを処理しているため、次のレコードを処理する前に、これらのファイルのファイルハンドルをクリーンアップして閉じる必要があります。

{
        # Read relevant fields from input file
        firstname=$1;
        lastname=$2;
        email=$3;
        title=$4;

        # Set output filename
        outfile=(output NR ".txt");

        # Read a line from template, replace special fields, and
        # print result to output file
        while ( (getline ln < template) > 0 )
        {
                sub(/{firstname}/,firstname,ln);
                sub(/{lastname}/,lastname,ln);
                sub(/{email}/,email,ln);
                sub(/{title}/,title,ln);
                print(ln) > outfile;
        }

        # Close template and output file in advance of next record
        close(outfile);
        close(template);
}

完了です。次のコマンドラインでスクリプトを実行します:

awk -f mail_merge.awk proposals.csv

または

awk -f mail_merge.awk < proposals.csv

現在のディレクトリに生成されたテキストファイルがあります。

高度なawk:単語の頻度カウント

awkの最も強力な機能の1つは、連想配列です。ほとんどのプログラミング言語では、配列エントリは通常、数値でインデックス付けされますが、awkでは、配列はキー文字列によって参照されます。ファイルproposals.txtからエントリを保存できます 前のセクションから。たとえば、次のような単一の連想配列の場合:

        proposer["firstname"]=$1;
        proposer["lastname"]=$2;
        proposer["email"]=$3;
        proposer["title"]=$4;

これにより、テキスト処理が非常に簡単になります。この概念を使用する単純なプログラムは、単語頻度カウンターのアイデアです。ファイルを解析し、各行の単語を分割して(句読点を無視して)、行の各単語のカウンターをインクリメントしてから、テキストに含まれる上位20語を出力できます。

まず、 wordscount.awkというファイルで 、フィールド区切り文字を空白と句読点を含む正規表現に設定します:

BEGIN {
        # ignore 1 or more consecutive occurrences of the characters
        # in the character group below
        FS="[ .,:;()<>{}@!\"'\t]+";
}

次に、メインループ関数は、空のフィールド(行の終わりに句読点がある場合に発生します)を無視して各フィールドを反復処理し、行内の単語の単語数を増やします。

{
        for (i = 1; i <= NF; i++) {
                if ($i != "") {
                        words[$i]++;
                }
        }
}

最後に、テキストが処理されたら、END関数を使用して配列の内容を出力し、awkの出力をシェルコマンドにパイプする機能を使用して数値ソートを実行し、最も頻繁に出現する20個の単語を出力します。

END {
        sort_head = "sort -k2 -nr | head -n 20";
        for (word in words) {
                printf "%s\t%d\n", word, words[word] | sort_head;
        }
        close (sort_head);
}

この記事の以前のドラフトでこのスクリプトを実行すると、次の出力が生成されました:

[[email protected]]$ awk -f wordcount.awk < awk_article.txt 
the     79
awk     41
a       39
and     33
of      32
in      27
to      26
is      25
line    23
for     23
will    22
file    21
we      16
We      15
with    12
which   12
by      12
this    11
output  11
function        11

次は何ですか?

その他のLinuxリソース

  • Linuxコマンドのチートシート
  • 高度なLinuxコマンドのチートシート
  • 無料のオンラインコース:RHELの技術概要
  • Linuxネットワーキングのチートシート
  • SELinuxチートシート
  • Linuxの一般的なコマンドのチートシート
  • Linuxコンテナとは何ですか?
  • 最新のLinux記事

awkプログラミングについて詳しく知りたい場合は、 Sed and awkという本を強くお勧めします。 デール・ドハティとアーノルド・ロビンスによる。

awkプログラミングを進めるための鍵の1つは、「拡張正規表現」を習得することです。 Awkは、すでにおなじみのsed正規表現構文にいくつかの強力な追加機能を提供します。

awkを学ぶためのもう1つの優れたリソースは、GNUawkユーザーガイドです。 awkの組み込み関数ライブラリの完全なリファレンスと、単純および複雑なawkスクリプトの例が多数あります。


Linux
  1. Linuxスキルを高めるための13の演習

  2. Linux –コマンドラインツールで2つのフォルダを同期する方法は?

  3. rsyncを使用してファイルをバックアップします

  1. Asciinemaとのターミナルセッションを記録する

  2. SELinuxでコンテナを保護する

  3. コマンド ライン ツールを使用して 2 つのフォルダーを同期する方法

  1. LynisでLinuxセキュリティをスキャンする

  2. tcpdumpを使用してネットワークのトラブルシューティングを行う

  3. コマンドラインスキルを磨くための10のチュートリアル