ファイル処理の際にデータを細かく切り出したり、必要な部分だけ抽出したりしたいときに便利なのがcutコマンドです。
本稿ではcutコマンドの使い方を丁寧に解説します。
目次
・cutコマンドの用法
・バイト数で斬る(-b)
・文字数で斬る(-c)
・区切り文字で斬る(-d,-f)
・Tips1:ディレクトリのパスを取ってくる
・Tips2:アウトプットの区切り文字を変える
cutコマンドの用法
cutコマンドの基本的な使い方は以下のようになります。
$ cut オプション 対象文字列
(※「$ 」はコマンド受付中のマークです。既に表示されているので皆さんが入力する必要はありません(環境によっては「# 」になっているかもしれません))
cutコマンドは単独で使うというよりは、echoやcat、sedなどの出力結果を受けて、細かい部分をさらに切り出す、というときに用いられることが多いコマンドです。また、cutコマンドも多分に漏れず引数が必ず必要ですが、1つ以上のオプションをちゃんと指定しないとエラーを返すという少し珍しいコマンドと言えるかもしれません。
今回は「nobel.txt」というデータセットを用いて使用法を見ていきましょう!
実際にコマンドを試してみたい方のために日本人ノーベル賞受賞者のうち、最初の10人の受賞年、名前(生年)、受賞分野のリストを作りましたので、必要に応じてご活用下さい。
» 日本人ノーベル賞受賞者最初の10人のリスト
1949/Hideki Yukawa(1907-1981)/Physics 1965/Sin-Itiro Tomonaga(1906-1979)/Physics 1968/Yasunari Kawabata(1899-1972)/Literature 1973/Reona Esaki(Leo Esaki)(1925-)/Physics 1974/Eisaku Sato(1901-1975)/Peace 1981/Kenichi Fukui(1918-1998)/Chemistry 1987/Susumu Tonegawa(1939-)/Physiology or Medicine 1994/Kenzaburo Oe(1935-)/Literature 2000/Hideki Shirakawa(1936-)/Chemistry
» 閉じる
cutコマンドを使う際はどこをどのように切り出すのかを指示してあげる必要があります。以下、各オプションを見ていきましょう。
バイト数で斬る(-b)
cutコマンドでは切り出すバイト数を指定することができます。例えばnobel.txtの各行の4バイト目を表示するには以下のようにします。
$ cut -b 4 nobel.txt
↓
9 5 8 3 4 1 7 4 0
1文字だけが欲しい場合はともかく、これだけでは何が何だか分かりません。
そこで「1バイト目から4バイト目」を切り出してみましょう。こういうときはハイフンを使用します。
$ cut -b 1-4 nobel.txt
↓
1949 1965 1968 1973 1974 1981 1987 1994 2000
これで受賞年を切り出すことができました。いまは「1」と最初のバイト数を指定しましたが、先頭のバイト数や文字を起点とする場合は
$ cut -b -4 nobel.txt
のように「1」の部分を省略することができます。また、日本語対応の環境であれば「-n」オプション(2バイト以上の文字を途中で切らないようにするオプション)と併用することもあります。
文字数で斬る(-c)
英数字の場合は-bオプションも-cオプションもほとんど変わらないので、こちらの-cオプションの方を使う機会が多いのではないかと思います。
$ cut -c 5- nobel.txt
↓
/Hideki Yukawa(1907-1981)/Physics /Sin-Itiro Tomonaga(1906-1979)/Physics /Yasunari Kawabata(1899-1972)/Literature /Reona Esaki(Leo Esaki)(1925-)/Physics /Eisaku Sato(1901-1975)/Peace /Kenichi Fukui(1918-1998)/Chemistry /Susumu Tonegawa(1939-)/Physiology or Medicine /Kenzaburo Oe(1935-)/Literature /Hideki Shirakawa(1936-)/Chemistry
ここでは5文字目以降を表示してみました。使い方は-bオプションと変わりません。また、カンマで区切れば複数の部分を切り出すこともできます。以下の例では6文字目~10文字目、18文字目~24文字目を切り出しています。
$ cut -c 6-10,18-24 nobel.txt
↓
Hideka(1907- Sin-Imonaga( Yasunabata(1 ReonaLeo Esa Eisak1901-19 Kenici(1918- Susumawa(193 Kenza(1935-) Hidekkawa(19
空白文字も含めてちゃんと抜き出せていますが、これでは意味のある文字列になっていませんね。
「-c」オプションは決まった形式のファイルや出力結果を整理するときに用いますが、文字数が様々に変動する出力に対応するのは難しいと言えます。このような場合はフレキシブルに対応できる「-d」オプションと「-f」オプションの合わせ技を使います。
区切り文字で斬る(-d,-f)
cutコマンドで最も強力な武器(?)がデリミタ(区切り文字)を指定したフィールド単位の切り出し機能です。このコマンドの書式は以下の通りです。
$ cut -d "区切り文字" -f n 対象文字列
「-d」オプションで区切り文字を指定して幾つかのフィールドに分け、「-f」オプションで左からn番目のフィールドを取ってくる、というコマンドです。
例えば
1949/Hideki Yukawa(1907-1981)/Physics
という一連の文字列は「/」という文字によって3つの領域に分けられています。この場合、nobel.txtの各行の真ん中、つまり2番目のフィールドを取ってきたい場合は次のようにします。
$ cut -d "/" -f 2 nobel.txt
↓
Hideki Yukawa(1907-1981) Sin-Itiro Tomonaga(1906-1979) Yasunari Kawabata(1899-1972) Reona Esaki(Leo Esaki)(1925-) Eisaku Sato(1901-1975) Kenichi Fukui(1918-1998) Susumu Tonegawa(1939-) Kenzaburo Oe(1935-) Hideki Shirakawa(1936-)
同様に、受賞分野を切り出したいときは
$ cut -d "/" -f 3 nobel.txt
とします。受賞年と受賞分野を一緒に抜き出すときはカンマで指定すればOKです。
$ cut -d "/" -f 1,3 nobel.txt
↓
1949/Physics 1965/Physics 1968/Literature 1973/Physics 1974/Peace 1981/Chemistry 1987/Physiology or Medicine 1994/Literature 2000/Chemistry
なお、デリミタ(区切り文字)は1文字しか設定できません。2文字以上を指定するとエラーが返ってきます。
$ cut -d "19" -f 1 nobel.txt
↓
cut: the delimiter must be a single character Try `cut --help' for more information.
勿論、ここまで紹介してきた切り出し操作は正規表現を用いたsedコマンドによっても可能ですが、ユーザーにとってはcutコマンドの方が分かりやすいと言えます。cutコマンドでは「-d」オプションを使用した複数フィールドの切り出しが特に有用です。
デリミタに空白(スペース)を使用することもできますが、タブ文字などがあると空白文字の数が変動しますのでcutコマンドはやや不向きです。こういうときは配列に入れてしまうか、awkコマンドで要素ごとに抜き出した方が良い気がします。
cutコマンドだけ、であったり、sedコマンドだけ、というように一つのコマンドに固執するのではなく、色々なコマンドを柔軟に使えると作業効率も上がると思います。(シェル芸人を目指している方におかれてはその限りではありませんが・・・)
Tips1:ディレクトリのパスを取ってくる
nobel.txtというファイルのパスが
「\home\user\ppp\qqq\rrr\nobel.txt」
であるとき、「\home\user\ppp\qqq\rrr」の部分は、文字列をひっくり返すrevコマンドを用いて切り出すことができます。
$ echo "/home/user/ppp/qqq/rrr/nobel.txt" | rev | cut -d "/" -f 2- | rev
↓
/home/user/ppp/qqq/rrr
Tips2:アウトプットの区切り文字を変える
「–output-delimiter=”xxx”」というオプションで指定することで出力時のデリミタをxxxに変えることができます。
$ cut -d "/" -f 1-2 nobel.txt --output-delimiter="%"
↓
1949%Hideki Yukawa(1907-1981) 1965%Sin-Itiro Tomonaga(1906-1979) 1968%Yasunari Kawabata(1899-1972) 1973%Reona Esaki(Leo Esaki)(1925-) 1974%Eisaku Sato(1901-1975) 1981%Kenichi Fukui(1918-1998) 1987%Susumu Tonegawa(1939-) 1994%Kenzaburo Oe(1935-) 2000%Hideki Shirakawa(1936-)
なお、アウトプットのデリミタの文字数は2文字以上でもOKです。「%」と文字列の間に空白文字を足してみます。
$ cut -d "/" -f 1-2 nobel.txt --output-delimiter=" % "
↓
1949 % Hideki Yukawa(1907-1981) 1965 % Sin-Itiro Tomonaga(1906-1979) 1968 % Yasunari Kawabata(1899-1972) 1973 % Reona Esaki(Leo Esaki)(1925-) 1974 % Eisaku Sato(1901-1975) 1981 % Kenichi Fukui(1918-1998) 1987 % Susumu Tonegawa(1939-) 1994 % Kenzaburo Oe(1935-) 2000 % Hideki Shirakawa(1936-)
cutコマンドはオプションの種類がそんなに多くないのでsedコマンドよりは慣れやすいと思います。cutもsedも便利なコマンドですので、適材適所で使ってあげましょう。