Linuxでテキストファイルの特定の列を表示する方法

特定の列を表示するコマンドは、入力形式で選びます。区切りが一文字で引用規則のない単純データなら cut、連続空白や条件・計算があるなら awk、RFC 形式の CSV なら CSV parser、目視用に整列するだけなら column です。「3列目」という言葉だけでは、区切り、空フィールド、引用された区切り、末尾空白の扱いが決まらないため、最初に数行を sed -n '1,5p' と od -An -t x1 で確認します。 確認ポイント:cutはdelimiter分割であり、引用符やdelimiter内包fieldを持つCSV parserではありません。

目次

cutとawkをdelimiterの性質で使い分ける

次のファイルはコロン区切りで、最後の一行だけ区切りを含みません。-d: が区切り、-f1,3 が第1列と第3列です。GNU cut では区切りは一バイトの文字を指定し、文字列 :: や正規表現は指定できません。

work=$(mktemp -d) || exit 1
trap 'rm -r -- "$work"' EXIT
printf 'name:city:score\nAki:Tokyo:90\nBo:Osaka:85\nno delimiter here\n' >"$work/report data.txt"
cut -d: -f1,3 -- "$work/report data.txt"

出力は name:score、Aki:90、Bo:85、no delimiter here の4行です。区切りがない行は既定で行全体がそのまま出ます。欠損行を捨てるなら -s を加え、cut -s -d: -f1,3 とすると最初の3行だけになります。「区切りなしを空の第3列として出す」動作ではないため、混在データで件数が必要なら、捨てる前に awk -F: 'NF<3 {print NR ":" $0}' で不正行を別に報告します。

範囲は -f2、-f1,3、-f2-4、-f3- のように指定します。出力区切りは既定で入力と同じです。GNU の --output-delimiter=, を使えば選んだフィールド間だけをカンマへ変えられますが、フィールド値中のカンマを引用して CSV にする機能ではありません。

cut -s -d: -f2 -- "$work/report data.txt"
cut -s -d: -f1,3 --output-delimiter=' | ' -- "$work/report data.txt"

第2列は city、Tokyo、Osaka です。次は name | score、Aki | 90、Bo | 85 です。--output-delimiter は GNU 拡張なので、移植用には cut の出力をそのまま使うか awk の OFS を明示します。

一バイト区切りと空フィールド

cut は区切りが連続すると、その間を空フィールドとして数えます。全角読点「、」や複数文字 :: を一つの delimiter にする用途には向きません。UTF-8 の「、」は複数バイトなので GNU cut の -d で一バイト区切りとして扱えず、エラーになる実装があります。複数文字や文字クラスが必要なら awk、厳密な構造形式なら専用 parser を使います。

printf 'A::90\nB:Osaka:80\n' >"$work/empty-field.txt"
cut -d: -f2 -- "$work/empty-field.txt" | sed -n l
printf 'A::90\n' | cut -d: -f2,3

sed -n l で行末を可視化した結果は一行目が $(空の第2列)、二行目が Osaka$ です。次の cut は空の第2列も保持するため :90 を出します。空を詰めて「90を第2列」とは数えません。入力スキーマが空フィールドを許すかを先に決め、列番号を固定します。

連続空白は awk の既定分割を使う

空白整形された表は、スペースが何個あるか一定とは限りません。cut -d ' ' -f2 は各スペースを別 delimiter とするため、連続スペースで空フィールドを返します。awk の既定 FS=" " は先頭・末尾空白を無視し、スペース、タブ、改行を含む空白の連続を区切りとして扱う特別な規則です。

printf 'Aki   Tokyo  90\nBo\tOsaka\t85\n' >"$work/space table.txt"
awk '{print $2}' "$work/space table.txt"
awk 'BEGIN {OFS=":"} {print $1,$3}' "$work/space table.txt"

出力は最初が Tokyo、Osaka、次が Aki:90、Bo:85 です。awk -F'[[:space:]]+' は見た目が似ても、正規表現 FS では先頭空白が空の第1フィールドを作り得るなど既定 FS=" " と細部が異なります。単なる空白列なら awk '{print $N}'、明示 delimiter なら awk -F: ... と分けます。

awk -F で条件付きの列を出す

awk -F: 'BEGIN {OFS=":"} NF==3 && $3+0 >= 90 {print $1,$3}' "$work/report data.txt"
printf 'awk_rc=%d\n' "$?"

出力はヘッダーを除けば Aki:90 で、終了値は0です。ただし awk は一致が0件でも通常0で終了します。0件を失敗にするなら awk -F: '$3+0>=90 {print $1; found=1} END{exit !found}' のように終了状態を設計します。$3+0 は非数値も0として扱うので、厳密な入力では $3 ~ /^[0-9]+$/ を先に検証します。引用した shell 変数を awk プログラムへ直接連結せず、awk -v min="$min" ... と値として渡します。

単純分割は CSV parser ではない

CSV はカンマ区切りに見えても、引用符内のカンマ、二重引用符のエスケープ、フィールド内改行を許します。cut -d, や awk -F, は引用状態を解釈しないため、一般の CSV parser ではありません。次の例では note 列の値が Tokyo, Japan ですが、単純分割は途中で切れます。

cat >"$work/data.csv" <<'CSV'
id,name,note
1,Aki,"Tokyo, Japan"
2,Bo,"said ""hello"""
CSV
cut -d, -f3 -- "$work/data.csv"
awk -F, '{print $3}' "$work/data.csv"

どちらも note の後、1件目を "Tokyo までしか出せず、2件目の引用解除も行いません。単純な -F, が使えるのは「値にカンマ、引用符、改行が絶対に入らない」とスキーマで保証された疑似CSVだけです。CSV なら、たとえば Python 3 標準 csv module で列を選びます。

python3 - "$work/data.csv" <<'PY'
import csv, sys
with open(sys.argv[1], newline='', encoding='utf-8') as f:
    for row in csv.reader(f):
        if len(row) < 3:
            raise SystemExit('short row')
        print(row[2])
PY

正確な出力は note、Tokyo, Japan、said "hello" です。文字コード、delimiter、quotechar が別仕様なら reader の引数をその仕様に合わせます。ファイル全体の dialect を推測だけで決めず、提供元の定義を確認します。

column は表示整形に限定する

column -t -s: は区切りデータを空白で揃え、人が端末で読む表にします。util-linux の版により -N、-J など利用可能な機能が異なるため column --version を確認します。整形後は空白幅や長い文字の表示幅が変わり、元の delimiter や空フィールド情報を失うことがあるため、後段の機械処理へ渡しません。

column -t -s: "$work/report data.txt"

先頭3行は概ね name city score、Aki Tokyo 90、Bo Osaka 85 と整列します。区切りなし行の扱いや空白幅は column の版・端末幅・文字幅判定で変わり得るため、これを exact data output として比較しません。抽出と検証は cut/awk/parser の構造化段階で終え、column は最後の目視表示だけにします。

ファイル名、失敗条件、検証

  • パスは -- "$file" または awk へ引用した一引数で渡し、cat $file | ... の未引用展開を避ける。
  • 区切りなし行を残すなら cut 既定、除外するなら -s。除外件数を事前に awk で数える。
  • 連続空白は awk の既定 FS、単一バイト delimiter は cut、引用規則のある CSV は CSV parser を選ぶ。
  • 抽出結果の行数と既知の先頭・末尾レコードを確認し、列ずれや短い行を検出する。
  • 本文の操作は読み取りのみで原本を変更しないため、ロールバックは不要。検証ファイルだけを trap で片付ける。

公式情報・参考資料

この記事を書いた人

実務の現場で詰まりがちなポイントを地図にするITブログ「IT trip」を運営。Windows/Office(Teams・Excel)からSQL、サーバ運用、ガジェットまで、再現性のある手順と“なぜそうなるか”を丁寧に解説します。読んだらすぐ試せること、そして迷った人の次の一歩が見えることを大切にしています。

コメント

コメントする

目次