🐧 Linux 総合学習プラットフォーム
正規表現・テキスト処理 ・ 中級

パイプでつなぐ定番テキスト加工

テキスト処理の力は、小さなコマンドをパイプ | でつなぐと一気に高まります。cut で列を切り出し、tr で文字を置換・削除し、sort で並べ替え、uniq で重複をまとめ、wc で行数を数える、といった部品を組み合わせます。定番は sort してから uniq -c で出現回数を数える流れで、ログの集計などで多用します。例えば cut -d: -f1 /etc/passwd | sort | uniq でユーザー名を重複なく並べられます。1つ1つは単純でも、つなぐことで実用的な集計が作れます。

ここまで grep・sed・awk を個別に見てきましたが、Linuxのテキスト処理が本当に強いのは、小さなコマンドをパイプ | でつないで組み合わせたときです。パイプは、あるコマンドの出力(標準出力)を、そのまま次のコマンドの入力(標準入力)へ渡す仕組みで、この一連のつながりをパイプラインと呼びます。1つ1つのコマンドは単純な仕事しかしませんが、それらを数珠つなぎにすることで、複雑な集計や抽出を一行で組み立てられます。「小さな道具を一つのことだけうまくやらせ、組み合わせて大きな仕事をする」というのが、Unix由来のテキスト処理の基本思想です。重要なのは、各コマンドが受け取るのも返すのも同じ「行の並んだテキスト」だという点で、この共通の形式があるからこそ、道具を自由に並べ替えたり差し替えたりできます。

つなぐための部品コマンド

パイプラインでよく使う部品をいくつか押さえておきましょう。cut は行から特定の列(フィールド)を切り出します。cut -d: -f1 /etc/passwd のように、-d で区切り文字、-f で何列目かを指定します。複数列なら -f1,3 や範囲指定の -f1-3 も使えます。tr は文字を置換・削除する道具で、tr 'a-z' 'A-Z' で小文字を大文字に変換したり、tr -d ' ' で空白を消したり、tr -s ' ' で連続する空白を1つにまとめたりできます。sort は行を並べ替え(数値順は -n、降順は -r)、uniq は隣り合う重複行をまとめます。wc は行数・単語数・文字数を数え、とくに wc -l で行数を数える使い方が頻出です。head と tail で先頭・末尾だけを取るのもパイプの定番です。これらを grep・sed・awk と組み合わせて、「絞る・取り出す・並べる・数える」を一筆書きにするのが基本になります。

定番パターン sort して uniq -c

もっともよく使う組み合わせの一つが、sort してから uniq -c で出現回数を数える流れです。ここで重要なのは、uniq は連続して並んだ重複しかまとめないので、先に sort で同じ行を隣り合わせてから渡す必要がある、という点です。uniq -c を使うと、各行の前に出現回数が付きます。たとえば cut -d: -f1 /etc/passwd | sort | uniq とすれば、ユーザー名を重複なく並べられます。アクセスログからアクセス元の多い順を出したいなら、対象を取り出してから sort | uniq -c | sort -rn のようにつなぐのが王道で、最後の sort -rn(-r は降順、-n は数値順)で件数の多い順に並べ替えます。たとえば awk '{print $1}' access.log | sort | uniq -c | sort -rn | head と書けば、アクセス元の上位だけをランキング表示できます。この「取り出す → 並べる → 数える → 並べ直す → 上位を見る」という流れは、ログ分析でそのまま何度も使える集計の型なので、丸ごと覚えておくと応用が効きます。

段階的に組み立てる

長いパイプラインは、いきなり全部を書こうとすると失敗します。こつは、左から1段ずつ足して、その都度結果を確かめながら組み立てることです。まず cut だけ実行して列が正しく取れているか見て、次に | sort を足し、さらに | uniq -c を継ぐ、というように段階的に伸ばします。たとえば「ログイン用シェルごとの利用人数」を出すなら、awk -F: '{print $NF}' /etc/passwd でまずシェルの列(最終フィールド)を取り、| sort で並べ、| uniq -c で数える、と一段ずつ確認しながら組めば、どこで意図とずれたかをすぐ特定できます。完成形だけを目指さず、中間出力を見ながら伸ばすのが、確実で速い作り方です。

よくある失敗

つまずきやすいのは、先ほど触れた「sort を省いて uniq を使う」ケースです。重複行が離れて並んでいると uniq はまとめてくれず、件数が正しく出ません。また、cut の -d で区切り文字を間違える(コロン区切りなのに既定のタブのままにするなど)と、列がずれて空の結果になります。tr は引数に2つの文字集合を取って変換しますが、削除したいときは -d を付けて集合を1つだけ渡す、という使い分けも混同しがちです。さらに、sort の数値順 -n を付け忘れると、10 が 9 より前に並ぶ「辞書順」になってしまい、件数の多い順のつもりが狂う、というのもありがちな落とし穴です。パイプの途中で結果がおかしくなったら、その手前までを実行して中間出力を確認するのが、原因切り分けの近道です。エラーメッセージが出なくても結果が空、というときほど、段階確認が効きます。

実務の使いどころ

実務では、ログ集計やデータの下ごしらえでパイプラインが日常的に活躍します。エラーの種類ごとの件数を出す、アクセスの多いURLを順位付けする、設定ファイルから有効な行だけを抜き出して整形する——いずれも grep で行を絞り、cut や awk で列(フィールド)を取り、sort・uniq・wc で集計する、という部品の組み合わせで実現できます。たとえば grep 'ERROR' app.log | awk '{print $4}' | sort | uniq -c | sort -rn は、エラー行だけを取り出してその種別を数え、多い順に並べる、という一連の分析をたった一行で表しています。一つ一つは単純でも、切り出し、並べ替え、数えるという流れをつなぐことで、専用ツールを書かずに実用的な分析が作れます。このパイプラインを自在に組み立てられることが、Linuxでのテキスト処理力そのものだと言ってよいでしょう。grep・sed・awk の各コマンドは、パイプでつないで初めて本領を発揮します。

この項目に出てくる用語

パイプラインぱいぷらいん
| でコマンドをつなぎ、出力を次の入力へ渡す仕組み。
フィールドふぃーるど
1行を区切り文字で分けた1つ1つの列。

関連コマンド

cuttrsortuniqwc

▶ 学習アプリでこの続きを学ぶ・演習する