はじめに
コマンドラインでのテキスト処理を学び始めると、多くの人がawkに出会います。
awkはシンプルな構文でありながら強力なデータ処理ができるツールですが、初学者がつまずきやすいポイントも少なくありません。
そのひとつが特殊変数NFの理解です。NFは一見地味ですが、実務でのログ解析やデータ整形では非常に重要な役割を果たします。
本記事では、awkにおけるNFの基本から応用までを、初学者の視点で丁寧に解説します。
単なるコマンドの説明ではなく、なぜその使い方になるのか、どこでつまずきやすいのかを意識して構成しています。流れを追いながら理解を深めていきましょう。
参考:GNU awk
awkにおける特殊変数「NF」の基礎定義と役割
ファイル作成
cat << 'EOF' > input.txt
apple orange banana
cat dog
red blue green yellow
EOF
実行コマンド
awk '{print NF}' input.txt
実行結果
3
2
4
実行コマンド
awk '{print $NF}' input.txt
実行結果
banana
dog
yellow
実行コマンド
awk '{print $1, $NF}' input.txt
実行結果
apple banana
cat dog
red yellow
仕組み
| 項目 | 内容 |
|---|---|
| NF | レコード(1行)内のフィールド数(列数)を表す特殊変数 |
| $NF | 最後のフィールドを指す(NF番目のフィールド) |
| $1 | 最初のフィールド |
| awkの動作 | 行ごとに処理し、自動でフィールド分割(デフォルトは空白区切り) |
| 応用例 | 列数の確認、最終列の抽出、可変長データ処理 |
解説
NF は各行のフィールド数を自動で保持するため、可変列データの処理に非常に便利です。
$NF を使うことで、列数が異なる場合でも常に「最後の値」を取得できます。
フィールド数参照と最終列抽出の使い分け
ファイル作成
cat << 'EOF' > input.txt
apple orange banana
cat dog
red blue green yellow
one
EOF
実行コマンド
awk '{print NF}' input.txt
実行結果
3
2
4
1
実行コマンド
awk '{print $NF}' input.txt
実行結果
banana
dog
yellow
one
仕組み
| 項目 | 内容 | 例("apple orange banana") |
|---|---|---|
| NF | フィールド数(列数)を表す組み込み変数 | 3 |
| $NF | 最終フィールドを取得 | banana |
| $1〜$n | 各フィールドを番号で参照 | $1=apple, $2=orange |
解説
NFは行ごとの列数を返し、$NFはその列数をインデックスとして最終列を取得します。
列数が可変なデータでは、この2つを使い分けることで柔軟に処理できます。
特定の列数を持つ行だけを抽出・フィルタリングする方法
ファイル作成
cat << 'EOF' > input.txt
a b c
1 2
x y z w
hello world
EOF
実行コマンド
awk 'NF==3' input.txt
実行結果
a b c
実行コマンド
awk 'NF==2' input.txt
実行結果
1 2
hello world
仕組み
| 要素 | 内容 |
|---|---|
| awk | テキスト処理ツール |
| NF | フィールド数(列数)を表す組み込み変数 |
| NF==3 | 列数が3の行のみ抽出 |
| NF==2 | 列数が2の行のみ抽出 |
| 区切り | デフォルトは空白(スペース・タブ) |
解説
NFは各行の列数を自動で数えるため、条件指定するだけで簡単にフィルタできます。
ログ整形や不正データ検出でよく使われる基本テクニックです。
NFをループ処理(for文)と組み合わせて全列を動的に操作
ファイル作成
cat << 'EOF' > input.txt
apple orange banana
cat dog
red blue green yellow
EOF
実行コマンド
awk '{print NF}' input.txt
実行結果
3
2
4
実行コマンド
awk '{
for(i=1; i<=NF; i++){
print "列" i ":" $i
}
}' input.txt
実行結果
列1:apple
列2:orange
列3:banana
列1:cat
列2:dog
列1:red
列2:blue
列3:green
列4:yellow
仕組み
| 要素 | 内容 |
|---|---|
| NF | 現在行のフィールド(列)数を保持 |
| $i | i番目のフィールドを参照 |
| for(i=1; i<=NF; i++) | 1列目から最終列までループ |
| 各フィールドを動的に出力 |
解説
NFを使うことで列数が異なるデータでも柔軟に処理できます。
for文と組み合わせることで全列を自動的に走査できるのがポイントです。
区切り文字(FS)の変更がNFの値に与える影響と注意点
ファイル作成
cat << 'EOF' > input.txt
apple orange banana
dog,cat,bird
one:two:three:four
EOF
実行コマンド
awk '{print $0 " -> NF=" NF}' input.txt
実行結果
apple orange banana -> NF=3
dog,cat,bird -> NF=1
one:two:three:four -> NF=1
実行コマンド
awk -F',' '{print $0 " -> NF=" NF}' input.txt
実行結果
apple orange banana -> NF=1
dog,cat,bird -> NF=3
one:two:three:four -> NF=1
実行コマンド
awk -F':' '{print $0 " -> NF=" NF}' input.txt
実行結果
apple orange banana -> NF=1
dog,cat,bird -> NF=1
one:two:three:four -> NF=4
仕組み
| FS(区切り文字) | 対象行 | 分割結果 | NF |
|---|---|---|---|
| デフォルト(空白) | apple orange banana | apple / orange / banana | 3 |
| デフォルト(空白) | dog,cat,bird | 1フィールド扱い | 1 |
| , | dog,cat,bird | dog / cat / bird | 3 |
| : | one:two:three:four | one / two / three / four | 4 |
| , or : | 区切り不一致の行 | 分割されず1フィールド | 1 |
解説
FSを変更すると分割単位が変わるため、NF(フィールド数)も大きく変わる。
入力データとFSが一致していない場合、意図せずNF=1になる点に注意。
可変長フォーマットのログファイルをNFで効率的に解析するテクニック
ファイル作成
cat << 'EOF' > input.txt
INFO 2026-05-01 userA login success
WARN 2026-05-01 userB disk almost_full
ERROR 2026-05-01 userC
DEBUG userD action=click button=submit extra=data
EOF
実行コマンド
awk '{print $0, "=> NF=" NF}' input.txt
実行結果
INFO 2026-05-01 userA login success => NF=5
WARN 2026-05-01 userB disk almost_full => NF=5
ERROR 2026-05-01 userC => NF=3
DEBUG userD action=click button=submit extra=data => NF=5
実行コマンド
awk 'NF < 5 {print "項目不足:", $0}' input.txt
実行結果
項目不足: ERROR 2026-05-01 userC
実行コマンド
awk '{print "最終フィールド:", $NF}' input.txt
実行結果
最終フィールド: success
最終フィールド: almost_full
最終フィールド: userC
最終フィールド: extra=data
仕組み
| 概念 | 説明 | 例 |
|---|---|---|
| NF | 行ごとのフィールド数 | NF=5 |
| $NF | 最後のフィールド | success |
| NF条件 | 可変長データの判定 | NF < 5 |
| 可変対応 | 列数が違っても処理可能 | エラーログ抽出 |
解説
awkのNFを使うことで、列数が不定なログでも柔軟に解析できます。
特に$NFと組み合わせると、末尾データの取得がシンプルに書けます。
条件分岐(if文)でNFを活用し、不完全なデータ行を除外するバリデーション手法
ファイル作成
cat << 'EOF' > input.txt
apple orange banana
grape
melon peach
kiwi
EOF
実行コマンド
awk '{ if (NF >= 2) print }' input.txt
実行結果
apple orange banana
melon peach
仕組み
| 要素 | 内容 |
|---|---|
| NF | フィールド数(空白区切りの列数) |
| 条件分岐 | if (NF >= 2) で2項目以上の行のみ出力 |
| 除外対象 | 1項目のみの不完全な行(例: grape, kiwi) |
| 処理内容 | if文で条件を満たす行だけprint |
解説
if文を使うことで条件の意図が明確になり、より読みやすいバリデーション処理になる。
NFは軽量で高速に判定できるのが強み。
NFから特定の列数を差し引いて「後ろからn番目」を指定する方法
ファイル作成
cat << 'EOF' > input.txt
a b c d e
1 2 3 4 5
x y z
EOF
実行コマンド
awk '{print $(NF)}' input.txt
実行結果
e
5
z
実行コマンド
awk '{print $(NF-1)}' input.txt
実行結果
d
4
y
実行コマンド
awk '{print $(NF-2)}' input.txt
実行結果
c
3
x
仕組み
| 式 | 意味 | 例(a b c d e) | 出力 |
|---|---|---|---|
| NF | フィールド総数 | 5 | e |
| NF-1 | 後ろから2番目 | 5-1=4 | d |
| NF-2 | 後ろから3番目 | 5-2=3 | c |
| $(NF-n) | 後ろから(n+1)番目 | 可変 | 任意 |
解説
NFは行内のフィールド数を表し、そこから引くことで後ろからの位置指定ができます。
$(NF-n)の形で柔軟に「後ろからn番目」の列を取得可能です。
awkとnfを使いこなすための理解のまとめ
awkにおけるNFは単なる「列数」以上の意味を持っています。
最終列の取得、データの整合性チェック、可変長データへの対応など、多くの場面で中核となる概念です。
初学者のうちは$NFやNF==数値といった基本的な使い方から始め、徐々にfor文や条件分岐と組み合わせていくのが理解への近道です。
![[sed] 実行して理解 指定した範囲の行を削除 文字列のsed](https://running-terminal-commands.com/wp-content/uploads/thumbnail_sed_1920_1080.png.webp)