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スクリプトの例が多数あります。