タブ区切りでフィールドを選択して出力する、または各行の中の一部を範囲指定して出力するコマンド。
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
-f3,1
とやっても-f1,3
と同じになり、フィールドの並び替えはできない。--help
--version
--
というパラメータを渡すとそれ以降のパラメータをオプションではなくファイル名とみなしてくれるので、-
で始まるファイル名を扱いたい場合に使うとよい。
-c
オプションは-b
と同じ2016/06/11-c
は文字単位で単位指定するオプションで、-b
とはマルチバイトの文字があったときに挙動が変わるはずだが、cutのソースコードを見るといまは-b
と-c
の実装はまったく同じのようである。
https://github.com/coreutils/coreutils/blob/a3311c966e34f2d9f8aa6b1de31b211124803d02/src/cut.c#L507
マニュアルを見ても確かに、いまは同じだが国際化対応をしたら挙動が変わる、というようなことが書いてある。
cat <file-path> | cut -d' ' -f1,3
cut
コマンドはデフォルトではカラムの区切りはタブ文字であり、cut -d' ' -f1,3
のようにすれば区切り文字はスペースになるが、いずれにしても区切り文字が連続する箇所はそこに空の列があるものとみなす。
そのため以下のような位置揃えをしてあるファイルを処理するのは苦手である。
$ cat foo.txt0 29 Danny m1 24 Jess m2 29 Joey m3 10 D.J. f4 5 Steph f5 0 Michelle f
こういう場合は以下のように連続するスペースを1つのタブに置換してしまうと楽である。
$ cat foo.txt | sed 's/[\t ]\+/\t/g' | cut -f3DannyJessJoeyD.J.StephMichelle
スペースの置換はsed
でなくてもperl
のワンライナーでもできるが、どうせperl
を使うなら、cut
ですることもperl
でやればいい。
$ cat foo.txt | perl -F'\s+' -anle 'print $F[2]'DannyJessJoeyD.J.StephMichelle
またはawk
コマンドを使ってもよい。awk
ではデフォルトで連続するスペースを1つの区切りとみなされる。
$ cat $p/tmp/test.txt | awk '{print $3}'DannyJessJoeyD.J.StephMichelle
cut
は-f
でフィールドを指定した場合、デフォルトでタブ区切りだが、コマンドラインからどうしてもタブ区切りであることを指定したい場合は、以下のように書けなくもない。
# 最初のカラムだけを表示cut -d$'\t' -f1
sort
でも似たような書き方でできる。
zshでは$
がいらないみたい。
ファイルではなく変数の値から一部を抜き出すには${VAR:S:L}
という書き方をする。すると、S
からL
文字分の部分文字列を抜き出せる。
s="abcdef"echo ${s:2:2}# => cd