Linuxで列を抽出するときは、最初にファイルが「タブ区切り」「一文字の区切り」「空白整形済み表」「正式なCSV」のどれかを確認します。単純な一文字区切りならcut、条件や計算を伴うならawk、引用符付きCSVならCSV対応パーサーを使います。位置だけで列を決める前にヘッダー、文字コード、改行、空欄の意味を確認し、元ファイルと同じパスへリダイレクトしません。まず小さな標本を表示し、新しい出力へ保存して、行数・列数・ヘッダー・欠損を検証するのが安全な流れです。
区切り・ヘッダー・文字コードを先に調べる
先頭数行はsed -n '1,5p' -- data.txtなどで読み取り専用に確認します。ただし個人情報や秘密を端末共有・ログへ表示しないよう、必要なら匿名化済み標本を用意します。タブは見た目が空白と区別しにくいため、データ仕様、生成元、バイト表示を併用し、見た目だけで区切りを決めません。
fileの判定は手掛かりであり、正式な形式保証ではありません。UTF-8か別符号化か、CRLFかLFか、BOMがあるか、ヘッダーが一行か、コメント行があるかを確認します。圧縮ファイルやバイナリを表形式と誤認せず、コピーまたは読み取り専用の入力から作業を始めます。
単純な一文字区切りはcutで抽出する
コロン区切りの第1列と第3列ならcut -d ':' -f 1,3 -- accounts.txtです。GNU cutのフィールド番号は1から始まり、既定の区切りはタブです。-dで入力区切りを指定し、-fへ列番号または範囲を渡します。ファイル名は引用し、オプションと誤認され得る名前には--を置きます。
cutは軽量でストリーム処理に向きますが、区切り文字を含む引用符付きフィールドを解析する道具ではありません。また-f 3,1のように指定順を変えても、選択列は入力で現れる順に出力されます。列を並べ替えたい場合はawkや形式対応ツールを使います。
区切りのない行と空フィールドを区別する
GNU cutは、指定した区切りを一つも含まない行を既定ではそのまま出力します。その行を除外する-sは便利ですが、異常行を黙って失う危険があります。まず-sなしで区切りのない行数を確認し、ヘッダー、空行、コメント、破損行のどれかを分類してから採否を決めます。
連続する区切りは空フィールドを表す場合があります。たとえばa::cの第2列は空であり、「列が存在しない」とは限りません。末尾区切り、空行、欠損値の扱いを仕様化し、抽出前後で行数だけでなく空欄件数も比較します。空欄を詰める整形を先に行うと列位置がずれるため避けます。
出力区切りを変えるときは意味を保つ
GNU cutには--output-delimiter=STRINGがあり、選んだ列の出力区切りを入力とは別にできます。ただし出力先をCSVと呼ぶなら、区切り・引用符・改行を正しくエスケープする必要があり、単にカンマを置くだけではCSVになりません。単純な内部データならタブなど衝突しない区切りを選び、形式名を正確に記録します。
NUL区切り入力向けのcut -zは、行終端を改行からNULへ変える機能で、通常の表の列区切りをNULへ設定する意味ではありません。ファイル名一覧のようなNUL終端データと、表のフィールド区切りを混同せず、後続コマンドも同じレコード終端へ対応していることを確認します。
空白区切りはawkの既定規則を理解する
空白で整形された表から第1列と第3列を出す基本形はawk '{print $1, $3}' -- report.txtです。awkの既定FS=" "は特殊で、先頭と末尾の空白を無視し、連続する空白・タブ・改行相当のまとまりでフィールドを分けます。人が読む可変幅表には便利ですが、空フィールドを保持したい固定形式には向きません。
「スペース一文字区切り」と「任意個の空白区切り」は別仕様です。単一文字のFSは各出現位置で分割するため、連続区切りから空フィールドが生じます。一方、正規表現のFSにはさらに別の規則があります。見本一行だけでなく、先頭空白、連続区切り、末尾空欄を含む試験データで番号を確認します。
固定タブならFSとOFSを明示する
タブ区切りで第1列と第3列を保つ例はawk -F '\t' -v OFS='\t' '{print $1, $3}' -- data.tsvです。FSは入力分割、OFSはprintで複数式を並べた際の出力区切りです。両方を明示すると、環境やコードの読み手による推測を減らせます。
列不足を除外するだけならawk -F '\t' -v OFS='\t' 'NF >= 3 {print $1, $3}' -- data.tsvと書けます。ただし除外件数を別に数えないと欠損を隠します。本番では正常出力と異常行の件数を記録し、異常行そのものに秘密がある場合は保護された場所へ限定して調査します。
条件付き抽出では型変換を意識する
列の値で絞るならawkが適します。たとえばタブ区切りの第1列が数字だけで10より大きい行の第2列はawk -F '\t' '$1 ~ /^[0-9]+$/ && $1 > 10 {print $2}' -- data.tsvです。数値条件の前に形式を検証し、見出しや10xを暗黙の数値変換へ任せません。
先頭ゼロ、小数点、指数表記、負数、桁区切り、ロケール依存小数点は要件次第です。識別子の0012を数値へ変えると意味が失われます。抽出条件、欠損時の扱い、比較の型を仕様として残し、代表値と境界値を含むテストで確認します。
正式なCSVを単純なカンマ分割で壊さない
CSVでは"Tokyo, Japan"のように引用されたカンマ、二重引用符、フィールド内改行があり得ます。そのためcut -d,やawk -F,は一般的なCSVパーサーではありません。列がずれても一見正常に見えるため、データ生成元が保証するCSV規則と、引用・改行を扱えるライブラリまたは専用ツールを選びます。
現在のGNU gawkには--csv(短縮形-k)があり、一般的なRFC 4180形式の引用カンマ、二重引用符、埋め込み改行、CRLFを扱えます。例はgawk --csv '{print $1, $3}' -- input.csvですが、出力を再びCSVにするには正しい引用処理も必要です。導入版をgawk --versionで確認し、POSIX awkへ同じオプションを期待しません。
ヘッダー名で列を確定し順序変更を検知する
第3列という位置は、生成側が列を追加すると別の意味になります。ヘッダーがある場合は必要な名前、重複名、大小文字、前後空白、文字コードを検証し、その名前から位置を解決します。CSVではヘッダー自体もCSV規則で解析し、単純なIFS=,分割を使いません。
出力にヘッダーを残すか、データ行だけにするかも明示します。ヘッダーを残すなら入力名をそのまま使うのか、出力仕様の標準名へ変えるのかを決めます。スケジュール処理では期待ヘッダーのハッシュまたは列名集合を検査し、変更時に失敗させる方が、誤った列を静かに配布するより安全です。
元ファイルと同じ出力先を指定しない
awk ... input.txt > input.txtのように入力と出力を同じパスにすると、シェルがコマンド開始前に出力を切り詰め、入力を失います。まずoutput.newのような別ファイルへ出し、正常終了、容量、行数、標本、アクセス権を確認します。シンボリックリンクや同一inodeの別名もあるため、名前が違うだけで安全とは決めつけません。
置換が必要でも、元データのバックアップ、所有者・モード・ACL・拡張属性・タイムスタンプ、同時読み書き、ファイルシステム境界を確認します。リダイレクトで作った新規ファイルは元のメタデータを自動継承しません。本文抽出だけが目的なら元を置換せず、派生物として別名保存するのが最も明確です。
大容量ファイルはストリーム性と長い行を試す
cutとawkは通常、入力を順次処理でき、全体をメモリへ載せる必要がありません。ただしCSVのフィールド内改行、極端に長い一行、巨大フィールド、正規表現、出力先の遅さで資源特性は変わります。実データを本番サーバーでいきなり処理せず、最大行長と代表サイズを測り、時間・メモリ・空き容量を制限環境で試します。
パイプ途中が失敗しても後段だけ成功したように見える構成があります。Bashで複数段を運用するならset -o pipefailの適否を検討し、各コマンドの終了状態と出力件数を記録します。一時出力がディスクを満たさないか、途中ファイルを他者が読めないか、再実行で混在しないかも確認します。
抽出結果を行数・列数・内容で検証する
成功判定を「コマンドが0で終わった」だけにしません。ヘッダーを除いた入力行数と出力行数、各行の期待列数、空欄件数、重複、先頭・末尾の代表値、文字化け、CR残存を比較します。意図的に除外した行があるなら、理由別件数の合計が入力件数と一致するようにします。
元ファイルと出力へsha256sumを取り、処理日時、コマンド版、ロケール、列仕様を記録すると再現しやすくなります。ただしハッシュは内容の正しさを証明せず、同じバイト列を識別するだけです。機密データの標本やエラー行をチケットへ貼らず、権限制御された監査記録へ必要最小限を残します。
確認チェックリスト
- 区切り・ヘッダー・文字コード・改行・空欄の意味を確認した
- 単純な一文字区切りだけをcutで扱った
- cutの番号が1始まりで指定順に並べ替わらないと理解した
- 区切りのない行と連続区切りの空フィールドを区別した
- awkのFSとOFS、既定の空白分割規則を明示した
- 引用符や埋め込み改行を含むCSVへ対応パーサーを使った
- 入力と同じパスへリダイレクトせず別出力を検証した
- 行数・列数・欠損・文字化け・終了状態を照合した

コメント