はじめに
テキストファイルには、さまざまな対応関係があります。文字を正規化する場合もあれば、2 つのファイルを行の位置で対応させる場合もあります。また、レコードが共通のキーを持つ場合もあります。オプションを暗記するより、対応関係に合ったツールを選ぶことが重要です。
この実験では、目的の異なる 3 つのツールを扱います。tr は文字ストリームを変換し、paste は行位置に基づいて行を結合し、join は共通フィールドを持つソート済みレコードを結合します。それぞれの入力を確認し、結果のファイルを検証してから、小さなレポートを作成します。
文字ストリームの変換とクリーニング
このステップでは、tr を使って文字を変換し、繰り返し現れる区切り文字を 1 つにまとめ、不要な文字を削除します。
意図的に不統一な行を作成します。cat -A を使うと、通常は見えない詳細を確認できます。スペースは空白として表示され、$ は行末を示します。これにより、何をクリーニングする必要があるかを正確に確認できます。
cd /home/labex/project/text-combine-lab
printf ' API,,,Worker,,WEB \n' > raw-services.txt
cat -A raw-services.txt
tr SET1 SET2 は、最初のセットに含まれる文字を、2 番目のセットの対応する文字に置き換えます。移植性のある文字クラス [:upper:] と [:lower:] は、それぞれ大文字と小文字を表します。
tr '[:upper:]' '[:lower:]' < raw-services.txt
次に、3 つの処理段階をパイプでつなぎます。最初の tr は大文字と小文字を変換します。tr -s ',' は、連続するカンマを 1 つのカンマに まとめます。tr -d ' ' はスペース文字を 削除します。tee は最終的なストリームを表示すると同時に保存します。
tr '[:upper:]' '[:lower:]' < raw-services.txt | tr -s ',' | tr -d ' ' | tee clean-services.txt
結果は api,worker,web になります。tr はストリームを読み取るだけで、入力ファイルをその場で編集することはありません。
paste で対応する行を結合する
このステップでは、1 行目同士、2 行目同士というように、行の位置が対応するファイルを結合します。
サービス名を 1 列に並べたファイルと、所有チームを 1 列に並べたファイルを作成します。
cd /home/labex/project/text-combine-lab
printf '%s\n' api worker web > services.txt
printf '%s\n' team-blue team-green team-blue > owners.txt
paste は、対応する行を横に並べます。デフォルトでは、区切り文字としてタブを使用します。
paste services.txt owners.txt
-d, を指定して区切り文字をカンマにし、tee を使って CSV 形式に近いファイルを表示・保存します。
paste -d, services.txt owners.txt | tee service-owners.csv
paste はキーを比較しません。一方のファイルで行が欠落したり、順序が入れ替わったりすると、対応する組み合わせも変わります。
共通キーでレコードを結合する
このステップでは、行の位置ではなく、1 番目のフィールドが一致するレコード同士を結合します。
区切り文字にスペースを使い、順序の異なる 2 つのテーブルを作成します。
cd /home/labex/project/text-combine-lab
printf '%s\n' 'web 8080' 'api 9000' 'worker 9100' > ports-unsorted.txt
printf '%s\n' 'worker active' 'web active' 'api maintenance' > states-unsorted.txt
join は、両方の入力が結合フィールドでソートされていることを前提とします。まず、ソート済みのコピーを作成します。sort -k1,1 では、-k がキーを選択し、1,1 は「フィールド 1 で開始し、フィールド 1 で終了する」ことを意味します。そのため、並べ替え順を決めるのはサービス名だけです。
sort -k1,1 ports-unsorted.txt > ports.txt
sort -k1,1 states-unsorted.txt > states.txt
内容を確認してから、フィールド 1 の値が一致するレコードを結合します。
cat ports.txt
cat states.txt
join ports.txt states.txt | tee service-details.txt
各結果には、共通するサービスキーが 1 回だけ表示され、その後にポートと状態が続きます。
読みやすいサービスレポートを作成する
このステップでは、元のテーブルを変更せずに、結合済みのレコードを別の形式に整えます。
スペースをカンマに変換して、シンプルなレポートを作成します。
cd /home/labex/project/text-combine-lab
tr ' ' ',' < service-details.txt | tee service-report.csv
2 つのコマンドをグループ化して、ヘッダーを追加します。波括弧を使うと、両方のコマンドの出力を 1 つのリダイレクト先に送れます。
{ echo 'service,port,state'; cat service-report.csv; } > service-report-with-header.csv
cat service-report-with-header.csv
ヘッダーを数えずにデータレコード数を数えます。
tail -n +2 service-report-with-header.csv | wc -l | tr -d ' ' > service-count.txt
cat service-count.txt
このワークフローでは、正規化したデータ、結合したデータ、整形したデータ、最終レポートという、小さく確認しやすい段階を維持できます。
まとめ
tr を文字単位の正規化に、paste を位置に基づく列の結合に、join をソート済みのキー関係の結合に使用しました。その後、元の入力を保持したまま、小さな処理段階を組み合わせて読みやすい CSV レポートを作成しました。



