タブ区切りファイルの並べ替え


180

次の形式のデータがあります。

foo<tab>1.00<space>1.33<space>2.00<tab>3

次に、最後のフィールドに基づいてファイルを降順に並べ替えようとしました。次のコマンドを試してみましたが、期待どおりに並べ替えられませんでした。

$ sort -k3nr file.txt  # apparently this sort by space as delimiter

$ sort -t"\t" -k3nr file.txt
  sort: multi-character tab `\\t'

$ sort -t "`/bin/echo '\t'`" -k3,3nr file.txt
  sort: multi-character tab `\\t'

それを行う正しい方法は何ですか?

こちらがサンプルデータです。

回答:


312

bashを使用して、これはトリックを行います:

$ sort -t$'\t' -k3 -nr file.txt

一重引用符で囲まれた文字列の前にドル記号があることに注意してください。これについては、bashの manページANSI-C引用セクションを参照してください


2
'"'"'エイリアス内で使用するために使用します。
パブロA

このデリミタを渡してawkコマンド内でソートする方法を示すことができますか?と同様ですがawk '{print $0 | "sort -nr" > "outfile" }' datafile、sortコマンドに送信されるエスケープされたタブ区切り文字が使用されます。
Merlin

11

デフォルトでは、フィールド区切り文字は非空白から空白への遷移なので、タブは問題なく機能するはずです。

ただし、列にはベース1とベース0のインデックスが付けられているため、おそらく

sort -k4nr file.txt

file.txtを列4で数値順に逆順にソートします。(質問のデータには5つのフィールドしかないため、最後のフィールドはインデックス5になります。)


4
これは、タブで区切られたフィールド間のスペース文字の数がすべての入力行で同じ場合にのみ機能します。
Lars Haugseth、2009年

5

-t \の後に実際のタブ文字を置く必要があります。それをシェルで行うには、ctrl-vを押してからタブ文字を押します。私が使用したほとんどのシェルは、リテラルタブエントリのこのモードをサポートしています。

ただし、別の場所からコピーして貼り付けると、通常はタブが保持されないので注意してください。


これが最良の(最も移植性のある)答えです。emacsでは、「引用挿入」モードでも実行できC-q <tab>ます。それ^Vもナノだと思います。
Wyatt8740

3

$ソリューションは私にとってはうまくいきませんでした。ただし、実際にコマンドにタブ文字自体を配置することで、sort -t '' -k2


1
<C-v><Tab>シェルでタブキーがオートコンプリートに使用される場合にタブを挿入するために使用します。
ユダRonen氏

1
ANSIクォート$'\t'は、ksh、zsh、およびbashで機能します。Bourneシェルはそれをサポートしていません。この投稿を参照してください:unix.stackexchange.com/a/371873/201820
codeforester

1

のようなものを通してそれをパイプしawk '{ print print $1"\t"$2"\t"$3"\t"$4"\t"$5 }'ます。これにより、スペースがタブに変更されます。


@MB:スペースを損なわないようにする必要があります。
neversaint

1
間違いなくよりクリーンな方法がありますが、awkを介してパイプ処理し、スペースをタブに変更し、データを並べ替え、再度awkを介してパイプ処理し、タブをスペースに戻すことを妨げるものはありません。
Michiel Buddingh、2009年

1
保存したいタブとスペースが混在している場合、これは機能しません。
James Thompson、

1

人々が常にタブとスペースを混同しているので、一般に、このようなデータを保持することは、それを回避できる場合に行うのに最適なことではありません。

Perl、Python、Rubyなどのスクリプト言語では、問題を簡単に解決できます。ここにいくつかのサンプルコードがあります:

#!/usr/bin/perl -w

use strict;

my $sort_field = 2;
my $split_regex = qr{\s+};

my @data;
push @data, "7 8\t 9";
push @data, "4 5\t 6";
push @data, "1 2\t 3";

my @sorted_data = 
    map  { $_->[1] }
    sort { $a->[0] <=> $b->[0] }
    map  { [ ( split $split_regex, $_ )[$sort_field], $_ ] }
    @data;

print "unsorted\n";
print join "\n", @data, "\n";
print "sorted by $sort_field, lines split by $split_regex\n";
print join "\n", @sorted_data, "\n";

1

WindowsでのGnuソートの解決策が必要でしたが、上記の解決策のいずれもコマンドラインで機能しませんでした。

ロイドの手がかりを使用して、次のバッチファイル(.bat)がうまくいきました。

二重引用符内にタブ文字を入力します。

C:\>cat foo.bat

sort -k3 -t"    " tabfile.txt

1
うん、ここでのトリックはそれ以外の場合は動作しません、.BATファイルでそれを入れている
カルロス・レンドン

1

'general-numeric-sort'を使用すると、bashシェルのcygwinのソートでこの問題が発生しました。私が指定した場合-t$'\t' -kFgFはフィールド番号である場合、それはうまくいきませんでしたが、私は両方の指定されたとき-t$'\t'とを-kF,Fg(例えば-k7,7g第7フィールドのために)それが仕事をしました。-kF,Fgせずに動作-t$'\t'しませんでした。


0

タブだけを用意することで簡単にしたい場合は、スペースをタブに置き換えます。

tr " " "\t" < <file> | sort <options>

私のtrはファイルを読み取らず、XDをストリーミングするだけです。usage: tr [-Ccsu] string1 string2
Unfun Cat

1
tr string1 string2 <some-file。stdinを読み取ることができる限り、すべてがファイルを読み取ることができます。
ランダルシュワルツ

0

Lars Haugsethの回答は、シェルスクリプトから実行した場合にこのエラーが発生するコマンドラインからのみ機能しました。

並べ替え:複数文字タブ '$ \ t'

誰かが見ているのであればそれがシェルスクリプトでコーディングされている場合の解決策は

sort -t'    '

タブ文字は引用符の間にあります。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.