cut コマンド

タブ区切りでフィールドを選択して出力する、または各行の中の一部を範囲指定して出力するコマンド。

cutコマンドの使用例と、同じことをするPerlワンライナーの例

## タブ区切りで最初の列と3列目だけを抽出して、タブ区切りで出力する
$ cut -f1,3 foo.txt
$ cat foo.txt | cut -f1,3
$ cat foo.txt | perl -anle 'print "$F[0]\t$F[2]"'

## 以下のようにしても列の順番は入れ替えてくれない
$ cut -f3,1 foo.txt
## Perlならできる
$ cat foo.txt | perl -anle 'print "$F[2]\t$F[0]"'

## 各行の4文字目以降を出力する
$ cut -b4- foo.txt
$ cat foo.txt | cut -b4-
$ cat foo.txt | perl -MEncode -nle 'print encode_utf8(substr(decode_utf8($_), 3))'

cutコマンドでできる処理であれば、Perlワンライナーを書くよりも簡単にできる。

インストール

Coreutilsというパッケージに入っているので、CentOSにもUbuntuにも始めから入っている。

オプション

-b
フィールド単位ではなくバイト単位で抽出する範囲を指定する
-c
フィールド単位ではなく文字単位で抽出する範囲を指定する。 いまの実装では -b と同じ。
--complement
抽出するフィールドは、-fで指定する番号以外のフィールドとする。
-d
フィールドのデリミタを指定する
-f
抽出するフィールドの番号を指定する。1から始まる番号でハイフンでの範囲指定や コンマ区切りで複数指定できる。 残念なことに -f3,1 とやっても -f1,3 と同じになり、フィールドの並び替えは できない。
--help
ヘルプ表示
--version
バージョン表示

-- というパラメータを渡すとそれ以降のパラメータをオプションではなくファイル名とみなしてくれるので、 - で始まるファイル名を扱いたい場合に使うとよい。

-c オプションは -b と同じ

-c は文字単位で単位指定するオプションで、-b とはマルチバイトの文字があったときに挙動が変わるはずだが、 cutのソースコードを見るといまは -b-c の実装はまったく同じのようである。

https://github.com/coreutils/coreutils/blob/a3311c966e34f2d9f8aa6b1de31b211124803d02/src/cut.c#L507

マニュアルを見ても確かに、いまは同じだが国際化対応をしたら挙動が変わる、というようなことが書いてある。

HOWTO

フィールドの区切りをタブではなくスペースにして処理するには

cat <file-path> | cut -d' ' -f1,3

1つ以上の連続するスペースまたはタブ文字を区切りとして処理するには

cutコマンドはデフォルトではカラムの区切りはタブ文字であり、 cut -d' ' -f1,3 のようにすれば区切り文字はスペースになるが、いずれにしても区切り文字が連続する箇所はそこに空の列があるものとみなす。

そのため以下のような位置揃えをしてあるファイルを処理するのは苦手である。

$ cat foo.txt
0   29     Danny   m
1   24      Jess   m
2   29      Joey   m
3   10      D.J.   f
4    5     Steph   f
5    0  Michelle   f

こういう場合は以下のように連続するスペースを1つのタブに置換してしまうと楽である。

$ cat foo.txt | sed 's/[\t ]\+/\t/g' | cut -f3
Danny
Jess
Joey
D.J.
Steph
Michelle

スペースの置換はsedでなくてもperlのワンライナーでもできるが、どうせperlを使うなら、 cutですることもperlでやればいい。

$ cat foo.txt | perl -F'\s+' -anle 'print $F[2]'
Danny
Jess
Joey
D.J.
Steph
Michelle

またはawkコマンドを使ってもよい。 awkではデフォルトで連続するスペースを1つの区切りとみなされる。

$ cat $p/tmp/test.txt | awk '{print $3}'
Danny
Jess
Joey
D.J.
Steph
Michelle

タブをコマンドラインから指定するには

cut-f でフィールドを指定した場合、デフォルトでタブ区切りだが、コマンドラインからどうしてもタブ区切りであることを指定したい場合は、以下のように書けなくもない。

# 最初のカラムだけを表示
cut -d$'\t' -f1

sort でも似たような書き方でできる。

zshでは $ がいらないみたい。

シェルスクリプトの変数に入っている文字列の一部を切り出すには

ファイルではなく変数の値から一部を抜き出すには ${VAR:S:L} という書き方をする。すると、SからL文字分の部分文字列を抜き出せる。

s="abcdef"
echo ${s:2:2}
# => cd
このサイトは筆者(hydrocul)の個人メモの集合です。すべてのページは永遠に未完成です。