Sortowanie pliku rozdzielanego tabulatorami

180

Mam dane w następującym formacie:

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

Teraz próbowałem posortować plik w oparciu o ostatnie pole malejąco. Próbowałem następujących poleceń, ale nie zostały posortowane zgodnie z oczekiwaniami.

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

Jak to zrobić?

Oto przykładowe dane .

Neversaint
źródło

Odpowiedzi:

312

Za pomocą bash to załatwi sprawę:

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

Zwróć uwagę na znak dolara przed ciągiem jednego cudzysłowu. Możesz o tym przeczytać w sekcjach cytowania ANSI-C na stronie podręcznika bash .

Lars Haugseth
źródło
2
Użyj, '"'"' aby użyć go w aliasie.
Pablo A
czy możesz pokazać, jak przekazać ten ogranicznik do sortowania w poleceniu awk? jak w awk '{print $0 | "sort -nr" > "outfile" }' datafile, z wyjątkiem delimitu tabulatora, który jest wysyłany do polecenia sortowania.
Merlin,
11

Domyślnie ogranicznik pola nie jest przejściem pustym do pustego przejścia, więc karta powinna działać dobrze.

Jednak kolumny są indeksowane jako podstawa 1 i podstawa 0, więc prawdopodobnie chcesz

sort -k4nr file.txt

posortować plik.txt według kolumny 4 numerycznie w odwrotnej kolejności. (Chociaż dane w pytaniu mają nawet 5 pól, więc ostatnim polem będzie indeks 5.)

laalto
źródło
4
Działa to tylko wtedy, gdy liczba znaków spacji między polami rozdzielanymi tabulatorami jest taka sama dla wszystkich wierszy wprowadzania.
Lars Haugseth
5

Musisz wstawić rzeczywisty znak tabulacji po -t \ i aby to zrobić w powłoce, naciśnij ctrl-v, a następnie znak tabulacji. Większość używanych przeze mnie powłok obsługuje ten tryb dosłownego wpisywania tabulatorów.

Uważaj jednak, ponieważ kopiowanie i wklejanie z innego miejsca zazwyczaj nie zachowuje zakładek.

Brian Carlsen
źródło
To najlepsza (najbardziej przenośna) odpowiedź. emacs pozwala ci to również zrobić w trybie „wstawiania cytatów”: C-q <tab>na przykład. Myślę, że to też jest ^Vw nano.
Wyatt8740
3

Rozwiązanie $ nie działało dla mnie. Jednak przez umieszczenie samego znaku tabulacji w poleceniu: sort -t '' -k2

Lloyd
źródło
1
Służy <C-v><Tab>do wstawiania tabulacji w przypadku użycia klawisza tab do automatycznego uzupełniania w powłoce.
Júda Ronén
1
Cytowanie ANSI $'\t'działa w ksh, zsh i bash. Powłoka Bourne'a nie obsługuje tego. Zobacz ten post: unix.stackexchange.com/a/371873/201820
codeforester
1

przepuść to przez coś takiego awk '{ print print $1"\t"$2"\t"$3"\t"$4"\t"$5 }'. Spowoduje to zmianę spacji na tabulatory.

Michiel Buddingh
źródło
@ MB: Muszę zachować nienaruszone miejsce.
Neversaint
1
Jest to niewątpliwie czystszy sposób, aby to zrobić, ale nic nie stoi na przeszkodzie, aby przesłać go przez awk, zmienić spacje na tabulatory, sortować dane, a następnie ponownie przesłać przez awk, zmieniając tabulatory z powrotem w spacje.
Michiel Buddingh
1
To nie zadziała, jeśli chcesz zachować tabulatory i spacje.
James Thompson
1

Zasadniczo przechowywanie takich danych nie jest dobrym rozwiązaniem, jeśli można tego uniknąć, ponieważ ludzie zawsze mylą tabulatory i spacje.

Rozwiązanie problemu jest bardzo proste w języku skryptowym, takim jak Perl, Python lub Ruby. Oto przykładowy kod:

#!/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
źródło
1

Chciałem rozwiązania dla Gnu sort w systemie Windows, ale żadne z powyższych rozwiązań nie działało dla mnie w wierszu poleceń.

Korzystając ze wskazówki Lloyda, dla mnie zadziałał następujący plik wsadowy (.bat).

Wpisz znak tabulacji w cudzysłowie.

C:\>cat foo.bat

sort -k3 -t"    " tabfile.txt
Lawrence Noronha
źródło
1
Tak, sztuczka polega na umieszczeniu go w pliku .bat, w przeciwnym razie nie zadziała
Carlos Rendon
1

Miałem ten problem z sortowaniem w cygwin w powłoce bash, gdy korzystałem z sortowania „general-numeric”. Jeśli podałem -t$'\t' -kFg, gdzie F jest numerem pola, to nie zadziałało, ale kiedy podałem oba -t$'\t'i -kF,Fg(np. -k7,7gDla 7. pola), zadziałało. -kF,Fgbez -t$'\t'nie działało.

Danny
źródło
0

Jeśli chcesz to ułatwić, mając tylko tabulatory, zamień spacje na tabulatory:

tr " " "\t" < <file> | sort <options>
The Unfun Cat
źródło
Mój tr nie czyta plików, tylko przesyła strumieniowo XD. usage: tr [-Ccsu] string1 string2
The Unfun Cat
1
tr string1 string2 <some-file. Wszystko może odczytać plik, o ile może odczytać standardowe wejście.
Randal Schwartz,
0

Odpowiedź Larsa Haugsetha działała dla mnie tylko z wiersza poleceń, gdzie daje ten błąd, jeśli została wykonana ze skryptu powłoki:

sortuj: wieloznakowa karta „$ \ t”

Rozwiązanie, jeśli jest zakodowane w skrypcie powłoki, jeśli ktoś go szuka

sort -t'    '

znak tabulacji znajduje się pomiędzy cytatem.

mightyandweakcoder
źródło