Ordinamento di un file delimitato da tabulazioni


180

Ho un dato con il seguente formato:

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

Ora ho provato a ordinare il file in base all'ultimo campo in modo decrescente. Ho provato i seguenti comandi ma non è stato ordinato come previsto.

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

Qual è il modo giusto per farlo?

Ecco i dati di esempio .

Risposte:


312

Usando bash , questo farà il trucco:

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

Notare il simbolo del dollaro davanti alla stringa a virgoletta singola. Puoi leggerlo nelle sezioni ANSI-C Quoting della pagina man di bash .


2
Utilizzare '"'"' per usarlo all'interno di un alias.
Pablo A

puoi mostrare come passare questo delimitatore per ordinare all'interno di un comando awk? come in awk '{print $0 | "sort -nr" > "outfile" }' datafile, ad eccezione di un delimitatore di tabulazioni di escape inviato al comando di ordinamento.
Merlin,

11

Per impostazione predefinita, il delimitatore di campo è una transizione da non vuota a vuota, quindi la scheda dovrebbe funzionare correttamente.

Tuttavia, le colonne sono indicizzate in base 1 e in base 0, quindi probabilmente lo desideri

sort -k4nr file.txt

per ordinare file.txt per colonna 4 numericamente in ordine inverso. (Sebbene i dati nella domanda abbiano anche 5 campi, quindi l'ultimo campo sarebbe l'indice 5.)


4
Funzionerà solo se il numero di spazi tra i campi separati da tabulazioni è lo stesso per tutte le righe di input.
Lars Haugseth,

5

Devi inserire un carattere di tabulazione reale dopo il -t \ e per farlo in una shell premi ctrl-v e poi il carattere di tabulazione. La maggior parte delle shell che ho usato supporta questa modalità di inserimento letterale.

Attenzione, però, perché la copia e incolla da un altro luogo generalmente non preserva le schede.


Questa è la risposta migliore (più portatile). emacs ti consente anche di farlo in modalità "quoted insert": C-q <tab>ad esempio. Penso che sia anche ^Vin nano.
Wyatt8740,

3

La soluzione $ non ha funzionato per me. Tuttavia, inserendo effettivamente il carattere di tabulazione stesso nel comando ha fatto: sort -t '' -k2


1
Utilizzare <C-v><Tab>per inserire la scheda nel caso in cui la chiave della scheda venga utilizzata per il completamento automatico nella shell.
Júda Ronén,

1
La quotazione ANSI $'\t'funziona in ksh, zsh e bash. La shell Bourne non lo supporta. Vedi questo messaggio: unix.stackexchange.com/a/371873/201820
codeforester

1

passalo attraverso qualcosa del genere awk '{ print print $1"\t"$2"\t"$3"\t"$4"\t"$5 }'. Questo cambierà gli spazi in schede.


@MB: devo mantenere intatto lo spazio.
neversaint,

1
C'è indubbiamente un modo più pulito per farlo, ma nulla ti impedisce di eseguire il piping attraverso awk, modificare gli spazi in schede, ordinare i dati e quindi reindirizzarli nuovamente in awk, cambiando nuovamente le schede in spazi.
Michiel Buddingh,

1
Ciò non funzionerà se è presente una combinazione di schede e spazi che si desidera conservare.
James Thompson,

1

In generale, conservare dati come questo non è una grande cosa da fare se si può evitarlo, perché le persone confondono sempre schede e spazi.

Risolvere il tuo problema è molto semplice in un linguaggio di scripting come Perl, Python o Ruby. Ecco qualche esempio di codice:

#!/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

Volevo una soluzione per l'ordinamento di Gnu su Windows, ma nessuna delle soluzioni precedenti ha funzionato per me sulla riga di comando.

Usando l'indizio di Lloyd, il seguente file batch (.bat) ha funzionato per me.

Digita il carattere di tabulazione tra virgolette doppie.

C:\>cat foo.bat

sort -k3 -t"    " tabfile.txt

1
Sì, il trucco qui è metterlo in un file .bat, altrimenti non funzionerà
Carlos Rendon,

1

Stavo avendo questo problema con l'ordinamento in cygwin in una shell bash quando usavo l'ordinamento numerico generale. Se ho specificato -t$'\t' -kFg, dove F è il numero del campo, non ha funzionato, ma quando ho specificato entrambi -t$'\t'e -kF,Fg(ad es. -k7,7gPer il 7 ° campo) ha funzionato. -kF,Fgsenza il -t$'\t'non ha funzionato.


0

Se vuoi renderti più semplice solo con le schede, sostituisci gli spazi con le schede:

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

Il mio tr non legge i file, trasmette solo XD. usage: tr [-Ccsu] string1 string2
The Unfun Cat,

1
tr string1 string2 <some-file. Tutto può leggere un file purché sia ​​in grado di leggere stdin.
Randal Schwartz,

0

La risposta di Lars Haugseth ha funzionato solo dalla riga di comando per me, dove dà questo errore se eseguita da uno script di shell:

ordina: scheda multi-carattere '$ \ t'

La soluzione se è codificata in uno script di shell se qualcuno lo sta cercando

sort -t'    '

il carattere di tabulazione è tra la citazione.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.