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 .

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 .


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.)


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.


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


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.


@ 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";

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

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.


0

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

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

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.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.