Menyortir file yang dibatasi tab

180

Saya memiliki data dengan format berikut:

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

Sekarang saya mencoba untuk mengurutkan file berdasarkan bidang terakhir yang semakin berkurang. Saya mencoba perintah berikut tetapi tidak diurutkan seperti yang kami harapkan.

$ 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'

Apa cara yang benar untuk melakukannya?

Berikut adalah contoh data .

neversaint
sumber

Jawaban:

312

Menggunakan bash , ini akan melakukan trik:

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

Perhatikan tanda dolar di depan string yang dikutip tunggal. Anda dapat membacanya di bagian ANSI-C Quoting di halaman bash man .

Lars Haugseth
sumber
2
Gunakan '"'"' untuk menggunakannya di dalam alias.
Pablo A
dapatkah Anda menunjukkan cara melewati delimeter ini untuk mengurutkan dalam perintah awk? seperti pada awk '{print $0 | "sort -nr" > "outfile" }' datafile, kecuali dengan delimeter tab yang lolos dikirim ke perintah sortir.
Merlin
11

Secara default pembatas bidang adalah transisi non-blank to blank sehingga tab akan berfungsi dengan baik.

Namun, kolom diindeks basis 1 dan basis 0 sehingga Anda mungkin mau

sort -k4nr file.txt

untuk mengurutkan file.txt dengan kolom 4 secara numerik dalam urutan terbalik. (Meskipun data dalam pertanyaan tersebut bahkan memiliki 5 bidang sehingga bidang terakhir adalah indeks 5.)

laalto
sumber
4
Ini hanya akan berfungsi jika jumlah karakter spasi antara bidang-bidang yang dipisahkan-tab adalah sama untuk semua jalur input.
Lars Haugseth
5

Anda harus meletakkan karakter tab yang sebenarnya setelah -t \ dan untuk melakukannya di shell Anda menekan ctrl-v dan kemudian karakter tab. Kebanyakan shell yang saya gunakan mendukung mode entri tab literal ini.

Berhati-hatilah, karena menyalin dan menempel dari tempat lain umumnya tidak mempertahankan tab.

Brian Carlsen
sumber
Ini adalah jawaban terbaik (paling portabel). emacs juga memungkinkan Anda melakukan itu dalam mode 'kutip dikutip': C-q <tab>misalnya. Saya pikir itu ^Vdi nano juga.
Wyatt8740
3

Solusi $ tidak bekerja untuk saya. Namun, dengan benar-benar menempatkan karakter tab itu sendiri di perintah lakukan: sort -t '' -k2

Lloyd
sumber
1
Gunakan <C-v><Tab>untuk memasukkan tab jika kunci tab digunakan untuk pelengkapan otomatis di shell Anda.
Júda Ronén
1
Mengutip ANSI $'\t'berfungsi dalam ksh, zsh, dan bash. Shell Bourne tidak mendukungnya. Lihat posting ini: unix.stackexchange.com/a/371873/201820
codeforester
1

pipa melalui sesuatu seperti awk '{ print print $1"\t"$2"\t"$3"\t"$4"\t"$5 }'. Ini akan mengubah spasi menjadi tab.

Michiel Buddingh
sumber
@ MB: Saya harus menjaga ruang tetap utuh.
neversaint
1
Tidak diragukan lagi ada cara yang lebih bersih untuk melakukannya, tetapi tidak ada yang mencegah Anda untuk mem-pipkannya melalui awk, mengubah spasi menjadi tab, menyortir data, dan kemudian menyalurkannya melalui awk lagi, mengubah tab kembali menjadi spasi.
Michiel Buddingh
1
Ini tidak akan berfungsi jika ada campuran tab dan spasi yang ingin Anda pertahankan.
James Thompson
1

Secara umum menyimpan data seperti ini bukan hal yang baik untuk dilakukan jika Anda bisa menghindarinya, karena orang selalu membingungkan tab dan spasi.

Memecahkan masalah Anda sangat mudah dalam bahasa scripting seperti Perl, Python atau Ruby. Berikut beberapa contoh kode:

#!/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";
James Thompson
sumber
1

Saya ingin solusi untuk pengurutan Gnu di Windows, tetapi tidak ada solusi di atas yang bekerja untuk saya di baris perintah.

Menggunakan petunjuk Lloyd, file batch berikut (.bat) bekerja untuk saya.

Ketikkan karakter tab di dalam tanda kutip ganda.

C:\>cat foo.bat

sort -k3 -t"    " tabfile.txt
Lawrence Noronha
sumber
1
Ya triknya di sini adalah meletakkannya di file .bat, jika tidak, itu tidak akan berhasil
Carlos Rendon
1

Saya mengalami masalah ini dengan mengurutkan cygwin di shell bash saat menggunakan 'general-numeric-sort'. Jika saya menentukan -t$'\t' -kFg, di mana F adalah nomor bidang, itu tidak berfungsi, tetapi ketika saya menentukan keduanya -t$'\t'dan -kF,Fg(misalnya -k7,7guntuk bidang ke-7) itu berhasil. -kF,Fgtanpa -t$'\t'tidak berhasil.

Danny
sumber
0

Jika Anda ingin membuatnya lebih mudah dengan hanya memiliki tab, ganti spasi dengan tab:

tr " " "\t" < <file> | sort <options>
Kucing Unfun
sumber
Tr saya tidak membaca file, hanya stream XD. usage: tr [-Ccsu] string1 string2
The Unfun Cat
1
tr string1 string2 <some-file. Semuanya bisa membaca file asalkan bisa membaca stdin.
Randal Schwartz
0

Jawaban Lars Haugseth hanya bekerja dari baris perintah untuk saya di mana ia memberikan kesalahan ini jika dijalankan dari skrip shell:

sortir: tab multi-karakter '$ \ t'

Solusinya jika dikodekan dalam skrip shell jika ada yang mencari

sort -t'    '

karakter tab ada di antara kutipan.

mightyandweakcoder
sumber