cut/paste/tr 入門 - 列の抽出と文字変換
この記事で解決できること
cutでフィールド・文字位置を指定して列を抽出できるpasteで複数ファイルを行単位で横結合できるtrで文字の変換・削除・圧縮ができる- 3 つのコマンドをパイプで組み合わせて実用的なテキスト処理ができる
結論(用途早見表)
| コマンド | 主な用途 |
|---|---|
cut |
CSV/TSV の特定列を取り出す |
paste |
複数ファイルを横に並べて結合する |
tr |
文字を 1 文字単位で変換・削除する |
前提(対象環境)
- OS:Ubuntu(GNU coreutils 版)
- macOS の
cut/trは動作が一部異なる場合がある
cut とは何か?
テキストの各行から、指定した列または文字位置を切り出すコマンド。CSV/TSV の加工や、ログから特定フィールドだけを抽出する場面で使う。
フィールド指定(-f / -d)
-d で区切り文字を指定し、-f で取り出すフィールド番号を指定する。
# カンマ区切りの 2 列目を取り出す $ echo "Alice,30,Tokyo" | cut -d, -f2 30 # TSV(デフォルト区切りはタブ)の 1〜2 列目 $ cut -f1,2 data.tsv # 3 列目以降をすべて取り出す $ cut -f3- data.tsv
文字位置指定(-c)
バイト・文字単位でスライスする。ログの固定長フィールドに使いやすい。
# 先頭 10 文字を取り出す $ cut -c1-10 access.log # 5 文字目以降をすべて取り出す $ cut -c5- access.log
-c はバイト数ではなく文字数を扱う(-b がバイト指定)。日本語を含むファイルでは -c が直感的。
cut でよくはまるポイントは何か?
フィールド番号は 1 始まり(0 ではない)。区切り文字が連続していてもそれぞれのフィールドとして扱われるため、空フィールドがある CSV に注意する。
# フィールド番号は 1 始まり $ echo "a:b:c" | cut -d: -f1 # → a $ echo "a:b:c" | cut -d: -f2 # → b $ echo "a:b:c" | cut -d: -f3 # → c # 空フィールドもカウントされる $ echo "a::c" | cut -d: -f2 # → (空行)
cut は複数の区切り文字(連続スペースなど)をまとめて扱えない。そのような場合は awk が適切。
paste とは何か?
複数のファイルを行ごとに横に並べて結合するコマンド。cat が縦(行追加)なら paste は横(列追加)という関係になる。
基本形
# 2 つのファイルを横結合(デフォルト区切りはタブ) $ paste names.txt scores.txt Alice 95 Bob 87 Carol 72 # 区切り文字をカンマに変える $ paste -d, names.txt scores.txt Alice,95 Bob,87 Carol,72
1 ファイルを複数列に並べる(-s)
-s で行を直列に並べる。1 カラムのリストを 1 行に結合したいときに使う。
$ cat items.txt apple banana cherry $ paste -s -d, items.txt apple,banana,cherry
tr とは何か?
文字を 1 文字単位でマッピングして変換するコマンド。ファイルではなく標準入力から受け取るため、パイプと組み合わせて使う。
文字変換
# 小文字 → 大文字 $ echo "hello world" | tr 'a-z' 'A-Z' HELLO WORLD # スペース → アンダースコア $ echo "foo bar baz" | tr ' ' '_' foo_bar_baz
文字削除(-d)
指定した文字を削除する。
# 数字を削除 $ echo "abc123def456" | tr -d '0-9' abcdef # 改行を削除(複数行を 1 行にする) $ tr -d '\n' < multiline.txt
連続文字の圧縮(-s)
同じ文字が連続している部分を 1 文字にまとめる。
# 複数スペースを 1 つにまとめる $ echo "foo bar baz" | tr -s ' ' foo bar baz # 複数改行を 1 つにまとめる $ tr -s '\n' < file.txt
tr は正規表現を使わない。パターンマッチが必要なら sed や awk を使う。
3 つのコマンドをパイプで組み合わせる
それぞれ単体では用途が限られるが、パイプで組み合わせると強力になる。
# CSV の 2 列目を取り出して大文字に変換 $ cut -d, -f2 users.csv | tr 'a-z' 'A-Z' # TSV の 1 列目を取り出し、改行を圧縮してカンマ区切りに結合 $ cut -f1 data.tsv | tr -s '\n' | paste -s -d, # ログの IP アドレス部分だけを抽出して重複を除く $ cut -d' ' -f1 access.log | sort -u
コマンドの使い分けまとめ
| 目的 | 使うコマンド |
|---|---|
| CSV/TSV の特定列を取り出す | cut -f N -d, |
| 固定長フィールドを切り出す | cut -c N-M |
| 複数ファイルを横結合する | paste |
| 1 ファイルの行を横並びにする | paste -s |
| 文字を変換する | tr SET1 SET2 |
| 特定の文字を削除する | tr -d SET |
| 連続文字を圧縮する | tr -s SET |
| 複数区切り文字や複雑なパターン | awk |
やってはいけないこと
cutでフィールド番号を 0 始まりと勘違いするtrに正規表現を渡そうとする(trは文字集合しか扱えない)pasteで行数が異なるファイルを結合する(空行が挿入される)
コピペ用:定番パターン
# CSV 2 列目を抽出 cut -d, -f2 file.csv # 先頭 5 文字を抽出 cut -c1-5 file.txt # 2 ファイルを横結合(CSV 形式) paste -d, file1.txt file2.txt # 小文字 → 大文字 tr 'a-z' 'A-Z' # スペース複数 → 1 つに圧縮 tr -s ' '