はじめに
awkはテキスト処理に特化した強力なコマンドで、ログ解析やCSV処理など幅広い場面で活用されます。
特にbeginブロックは、処理の起点として重要な役割を持ちますが、初学者がつまずきやすいポイントでもあります。
本記事では、awkの基本構造と処理フローを押さえつつ、beginの使い方を中心に実践的な知識を整理します。
参考: gawk manual
awkの基本構造と処理フロー(BEGIN | MAIN | END)
ファイル作成
cat << 'EOF' > input.txt
apple 100
banana 200
orange 300
EOF
実行コマンド
awk 'BEGIN { print "=== 開始処理 ===" }
{ print "商品:", $1, "価格:", $2 }
END { print "=== 終了処理 ===" }' input.txt
実行結果
=== 開始処理 ===
商品: apple 価格: 100
商品: banana 価格: 200
商品: orange 価格: 300
=== 終了処理 ===
仕組み
| フェーズ | タイミング | 役割 | 記述例 |
|---|---|---|---|
| BEGIN | 入力処理の前 | 初期化・ヘッダ出力 | BEGIN { print "開始" } |
| MAIN | 各行ごと | データ処理 | { print $1, $2 } |
| END | 入力処理の後 | 集計・終了処理 | END { print "終了" } |
解説
BEGINは処理前、MAINは各行、ENDは処理後に実行される3段構造です。
この流れを理解すると、awkでのデータ処理の設計がシンプルになります。
変数・配列の初期化:プログラム実行前に準備すること
ファイル作成
cat << 'EOF' > input.txt
apple 100
banana 200
orange 150
apple 50
EOF
実行コマンド
awk 'BEGIN { sum=0; count=0 } { sum+=$2; count++ } END { print "sum="sum, "avg="sum/count }' input.txt
実行結果
sum=500 avg=125
実行コマンド
awk 'BEGIN { } { arr[$1]+=$2 } END { for (key in arr) print key, arr[key] }' input.txt
実行結果
apple 150
banana 200
orange 150
仕組み
| セクション | タイミング | 内容 | 役割 |
|---|---|---|---|
| BEGIN | 実行前 | sum=0, count=0 | 変数の初期化 |
| 本処理 | 行ごと | sum+=$2, count++ | データの集計 |
| 本処理 | 行ごと | arr[$1]+=$2 | キーごとの集計 |
| END | 実行後 | 平均計算・出力 | 結果の表示 |
解説
BEGINで配列や変数を準備し、処理中にキーごとに値を蓄積します。
awkの配列は連想配列のため、文字列キーで柔軟に集計できます。
組み込み変数(FS, OFS, RS, ORS)の定義方法
ファイル作成
cat << 'EOF' > input.txt
A 1
B 2
C 3
EOF
実行コマンド
awk 'BEGIN{FS=" "; OFS=","} {print $1,$2}' input.txt
実行結果
A,1
B,2
C,3
実行コマンド
awk 'BEGIN{RS="\n"; ORS="---\n"} {print $0}' input.txt
実行結果
A 1---
B 2---
C 3---
仕組み
| 変数 | 意味 | 設定例 | 効果 |
|---|---|---|---|
| FS | 入力フィールド区切り | FS=" " | 行をスペースで分割 |
| OFS | 出力フィールド区切り | OFS="," | 出力時にカンマ区切り |
| RS | 入力レコード区切り | RS="\n" | 行単位で処理 |
| ORS | 出力レコード区切り | ORS="---\n" | 出力行の末尾を変更 |
解説
BEGINブロックで組み込み変数を定義すると、入力処理前に区切りルールを変更できます。
これにより入力解析と出力形式を柔軟に制御できます。
BEGINのみを使用した「ファイル入力を必要としない」計算・出力
実行コマンド
awk 'BEGIN { print "Hello, awk BEGIN!" }'
実行結果
Hello, awk BEGIN!
実行コマンド
awk 'BEGIN { sum=0; for(i=1;i<=5;i++) sum+=i; print sum }'
実行結果
15
仕組み
| 要素 | 内容 | 説明 |
|---|---|---|
| BEGIN | 前処理ブロック | 入力ファイルを読む前に実行される |
| 出力命令 | 標準出力へ結果を表示 | |
| 変数 | sum, i | awk内で自動生成される |
| for文 | 繰り返し処理 | ループで計算を実行 |
| 入力ファイル | 不要 | BEGINのみで処理完結 |
解説
BEGINブロックは入力なしで実行されるため、awk単体で計算や出力が可能です。
簡易スクリプトやワンライナー計算に非常に便利です。
CSV処理におけるヘッダー情報の出力
ファイル作成
cat << 'EOF' > input.txt
name,age,city
Alice,30,Tokyo
Bob,25,Osaka
Charlie,35,Nagoya
EOF
実行コマンド
awk 'BEGIN { print "name,age,city" } { print }' input.txt
実行結果
name,age,city
name,age,city
Alice,30,Tokyo
Bob,25,Osaka
Charlie,35,Nagoya
実行コマンド
awk 'BEGIN { print "HEADER: name,age,city" } NR>1 { print }' input.txt
実行結果
HEADER: name,age,city
Alice,30,Tokyo
Bob,25,Osaka
Charlie,35,Nagoya
仕組み
| 要素 | 内容 |
|---|---|
| BEGIN | 入力処理前に一度だけ実行されるブロック |
| NR | 現在のレコード番号(行番号) |
| NR>1 | 1行目(元のヘッダー)をスキップ |
| 行または文字列を出力 |
解説
BEGINを使うことで、入力ファイルとは独立してヘッダーを先に出力できる。
NR条件と組み合わせることで既存ヘッダーの除外や加工が柔軟に行える。
外部引数(-v オプション)とBEGINブロックの優先順位
ファイル作成
cat << 'EOF' > input.txt
apple 100
banana 200
EOF
実行コマンド
awk 'BEGIN { x=1 } { print x, $0 }' input.txt
実行結果
1 apple 100
1 banana 200
実行コマンド
awk -v x=2 'BEGIN { } { print x, $0 }' input.txt
実行結果
2 apple 100
2 banana 200
実行コマンド
awk -v x=2 'BEGIN { x=1 } { print x, $0 }' input.txt
実行結果
1 apple 100
1 banana 200
仕組み
| 項目 | 内容 |
|---|---|
| -v オプション | awk実行前に変数を初期化 |
| BEGINブロック | スクリプト開始時に実行される |
| 優先順位 | BEGIN内の代入が最終的に上書きする |
| 評価タイミング | -v → BEGIN → 本処理 の順で実行 |
解説
-vで渡した値は初期値として設定され、その後BEGINブロックで再代入されると上書きされる。
つまり最終的な値はBEGINの処理結果が優先される。
ENDブロックとの組み合わせによる集計処理の完結
ファイル作成
cat << 'EOF' > input.txt
Alice 10
Bob 20
Alice 15
Bob 5
Charlie 30
EOF
実行コマンド
awk '
BEGIN { print "集計開始" }
{ sum[$1] += $2 }
END {
print "集計結果"
for (name in sum) {
print name, sum[name]
}
}
' input.txt
実行結果
集計開始
集計結果
Bob 25
Alice 25
Charlie 30
仕組み
| ブロック | 役割 | 内容 |
|---|---|---|
| BEGIN | 初期処理 | 処理開始時に一度だけ実行 |
| メイン処理 | 行ごとの処理 | 名前ごとに数値を加算 |
| END | 後処理 | 全処理終了後に集計結果を出力 |
解説
BEGINで初期化し、通常ブロックでデータを蓄積、ENDでまとめて出力することで、awk単体で集計処理を完結できます。
BEGINを使いこなして可読性の高いスクリプトを書くコツ
ファイル作成
cat << 'EOF' > input.txt
apple 100
banana 200
orange 150
EOF
実行コマンド
awk 'BEGIN { print "=== Fruit Price List ===" } { print $1, $2 "yen" } END { print "=== End ===" }' input.txt
実行結果
=== Fruit Price List ===
apple 100yen
banana 200yen
orange 150yen
=== End ===
仕組み
| ブロック | タイミング | 役割 |
|---|---|---|
| BEGIN | 読み込み前 | ヘッダー出力・初期化処理 |
| 本文 {} | 各行ごと | データ処理(フィールド操作など) |
| END | 読み込み後 | フッター出力・集計結果表示 |
解説
BEGINを使うと前処理を明確に分離でき、スクリプトの可読性が大きく向上します。
特にヘッダーや初期化処理を書くと構造が整理されます。
BEGINブロックでよく発生するエラーと対処法
ファイル作成
cat << 'EOF' > input.txt
apple 100
banana 200
orange 300
EOF
実行コマンド
awk 'BEGIN { print total } { total += $2 } END { print total }' input.txt
実行結果
600
実行コマンド
awk 'BEGIN { total=0 } { total += $2 } END { print total }' input.txt
実行結果
600
実行コマンド
awk 'BEGIN { print $1 }' input.txt
実行結果
実行コマンド
awk '{ print $1 }' input.txt
実行結果
apple
banana
orange
仕組み
| 項目 | 内容 |
|---|---|
| BEGINブロック | 入力処理前に一度だけ実行される |
| フィールド変数 ($1など) | 入力行が読まれて初めて利用可能 |
| 未初期化変数 | 0または空文字として扱われる |
| メインブロック {} | 各行ごとに処理される |
| ENDブロック | 全処理終了後に一度実行 |
解説
BEGINは入力前に実行されるため、行データやフィールドは使えない点が典型的な落とし穴です。
変数初期化専用として使うのが安全です。
awkとbeginを使いこなすためのポイント
awkにおけるbeginは単なる開始処理ではなく、スクリプト全体の設計に関わる重要な要素です。
BEGINでの初期化や設定が適切であれば、MAINやENDの処理はシンプルかつ明確になります。特にCSV処理や集計処理ではその効果が顕著です。
初学者のうちは「どの処理をどこに書くべきか」を意識しながら、小さなスクリプトで試行錯誤することが理解への近道です。
