サーチ…
前書き
cut
コマンドは、テキストファイルの行の一部を高速に抽出する方法です。それは最も古いUnixコマンドに属します。その最も普及した実装は、Linux上に見られるGNU版とMacOS上に見出されるFreeBSD版ですが、Unixのそれぞれの特色は独自のものです。違いについては以下を参照してください。入力行は、 stdin
から、またはコマンド行で引数としてリストされたファイルから読み込まれます。
構文
cut -f1,3#最初と 3番目のタブ区切り フィールドを抽出する(stdinから)
cut -f1-3#最初から 3番目のフィールドから抽出する (両端を含む)
カット-f-3#-3は1-3と解釈されます
cut -f2-#2-は2番目から最後まで解釈されます
cut -c1-5,10#stdinから1,2,3,4,5,10の位置にある文字を抽出します。
cut -s -f1#区切り文字を含まない行を抑制する
cut --complement -f3#(GNUカットのみ)3番目のフィールドを除く すべてのフィールドを抽出する
パラメーター
パラメータ | 詳細 |
---|---|
-f、--fields | フィールドベースの選択 |
-d、--delimiter | フィールドベースの選択の区切り文字 |
-c、--characters | 文字ベースの選択、区切り文字無視またはエラー |
-s、--only-delimited | デリミタ文字を含まない行を表示しない(そうでない場合は印刷される) |
- 補体 | 反転された選択(指定されたフィールド/文字を除くすべてを抽出 |
- 出力デリミタ | 入力区切り文字と異なる必要があるときを指定する |
備考
1.構文の違い
上記の表の長いオプションは、GNUバージョンでのみサポートされています。
2.キャラクターは特別な扱いを受けない
FreeBSD cut
(例えばMacOSに付属)には--complement
スイッチがありません。文字範囲の場合は、代わりにcolrm
コマンドを使うことができます:
$ cut --complement -c3-5 <<<"123456789"
126789
$ colrm 3 5 <<<"123456789"
126789
しかし、大きな違いがあります。なぜなら、 colrm
はTAB文字(ASCII 9)を実際の表colrm
として8の次の倍数に、バックスペース(ASCII 8)を-1として扱うからです。逆に、 cut
はすべての文字を1列幅として扱います。
$ colrm 3 8 <<<$'12\tABCDEF' # Input string has an embedded TAB
12ABCDEF
$ cut --complement -c3-8 <<<$'12\tABCDEF'
12F
3.(まだまだ)国際化
cut
が設計されたとき、すべての文字は1バイト長であり、国際化は問題ではありませんでした。より広範な文字を持つシステムを書くことが一般的になったとき、POSIXが採用した解決策は、バイト数が何バイトであろうと、文字の選択という意味を保持すべき古い-c
スイッチと、新しいスイッチ-b
を導入することです。現在の文字エンコーディングに関係なく、 バイトを選択します 。最も一般的な実装では、 -b
が導入され、動作しますが、 -c
は-b
とまったく同じように動作します。たとえば、GNU cut
:
SEの迷惑メールフィルタは、孤立した漢字で英語のテキストをブラックリストに載せているようだ。私はこの制限を克服することができなかったので、以下の例はあまり表現力がありません。
# In an encoding where each character in the input string is three bytes wide,
# Selecting bytes 1-6 yields the first two characters (correct)
$ LC_ALL=ja_JP.UTF-8 cut -b1-6 kanji.utf-8.txt
...first two characters of each line...
# Selecting all three characters with the -c switch doesn’t work.
# It behaves like -b, contrary to documentation.
$ LC_ALL=ja_JP.UTF-8 cut -c1-3 kanji.utf-8.txt
...first character of each line...
# In this case, an illegal UTF-8 string is produced.
# The -n switch would prevent this, if implemented.
$ LC_ALL=ja_JP.UTF-8 cut -n -c2 kanji.utf-8.txt
...second byte, which is an illegal UTF-8 sequence...
文字がASCII範囲外で、 cut
を使用する場合は、エンコーディングの文字幅を常に認識し、それに応じて-b
を使用する必要があります。文書化されているように-c
が動作し始めると、スクリプトを変更する必要はありません。
4.速度の比較
cut
の限界は人々にその有用性を疑わせる。実際、より強力でより一般的なユーティリティによって同じ機能を実現することができます。しかし、 cut
の利点はその性能です。いくつかの速度の比較については下記を参照してください。 test.txt
は300万行があり、空白で区切られた5つのフィールドがそれぞれあります。 awk
テストでは、 mawk
が使われました。なぜなら、それはGNU awk
より速いからです。シェル自体(最後の行)ははるかに最悪のパフォーマーです。与えられたtime
(秒)は、 time
コマンドがリアルタイムで与えるものです。
(誤解を避けるために、テストされたすべてのコマンドは、与えられた入力で同じ出力を出しましたが、もちろん同等ではなく、さまざまな状況で異なる出力を与えます。特に、フィールドが可変スペースで区切られている場合)
コマンド | 時間 |
---|---|
cut -d ' ' -f1,2 test.txt | 1.138秒 |
awk '{print $1 $2}' test.txt | 1.688秒 |
join -a1 -o1.1,1.2 test.txt /dev/null | 1.767秒 |
perl -lane 'print "@F[1,2]"' test.txt | 11.390秒 |
grep -o '^\([^ ]*\) \([^ ]*\)' test.txt | 22.925秒 |
sed -e 's/^\([^ ]*\) \([^ ]*\).*$/\1 \2/' test.txt | 52.122秒 |
while read ab _; do echo $a $b; done <test.txt | 55.582秒 |
5.参照マニュアルページ
基本的な使用法
一般的な使用法は、各行が区切り文字で区切られたフィールドで構成され、 -d
オプションで指定されたCSV形式のファイルです。デフォルトの区切り文字はTAB文字です。 data.txt
ような行を持つデータファイルがあるとします
0 0 755 1482941948.8024
102 33 4755 1240562224.3205
1003 1 644 1219943831.2367
その後、
# extract the third space-delimited field
$ cut -d ' ' -f3 data.txt
755
4755
644
# extract the second dot-delimited field
$ cut -d. -f2 data.txt
8024
3205
2367
# extract the character range from the 20th through the 25th character
$ cut -c20-25 data.txt
948.80
056222
943831
いつものように、スイッチとそのパラメータの間にはオプションのスペースがあります: -d,
-d ,
と同じですが-d ,
GNU cut
は--output-delimiter
オプションを指定することができます(この例の独立した特徴は、シェルによる特殊な処理を避けるために入力区切り文字としてのセミコロンをエスケープする必要があるということです)
$ cut --output-delimiter=, -d\; -f1,2 <<<"a;b;c;d"
a,b
1つの区切り文字
-d ",;:"
ようなものを指定した場合、デリミタ(この場合はカンマ)として最初の文字のみが使用されます。他の実装(GNU cut
)では、エラーメッセージが表示されます。
$ cut -d ",;:" -f2 <<<"J.Smith,1 Main Road,cell:1234567890;land:4081234567"
cut: the delimiter must be a single character
Try `cut --help' for more information.
繰り返されるデリミタは空のフィールドとして解釈されます
$ cut -d, -f1,3 <<<"a,,b,c,d,e"
a,b
スペースで区切られた文字列では、いくつかの文字列にはあまり明らかではないかもしれません
$ cut -d ' ' -f1,3 <<<"a b c d e"
a b
shellや他のプログラムのように引数を解析するためにcut
を使うことはできません。
引用なし
区切り文字を保護する方法はありません。スプレッドシートや同様のCSV処理ソフトウェアは通常、区切り文字を含む文字列を定義できるテキスト引用文字を認識できます。 cut
はできません。
$ cut -d, -f3 <<<'John,Smith,"1, Main Street"'
"1
抽出する、操作しない
行の一部だけを抽出し、フィールドの順序を変更したり繰り返すことはできません。
$ cut -d, -f2,1 <<<'John,Smith,USA' ## Just like -f1,2
John,Smith
$ cut -d, -f2,2 <<<'John,Smith,USA' ## Just like -f2
Smith