Ordenar un archivo delimitado por tabulaciones

180

Tengo datos con el siguiente formato:

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

Ahora intenté ordenar el archivo en función del último campo de forma decreciente. Intenté los siguientes comandos pero no se ordenó como esperábamos.

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

¿Cuál es la forma correcta de hacerlo?

Aquí están los datos de muestra .

Neversaint
fuente

Respuestas:

312

Usando bash , esto hará el truco:

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

Observe el signo de dólar frente a la cadena entre comillas simples. Puede leer sobre esto en las secciones de Citas ANSI-C de la página del manual de bash .

Lars Haugseth
fuente
2
Use '"'"' para usarlo dentro de un alias.
Pablo A
¿Puedes mostrar cómo pasar este delímetro para ordenar dentro de un comando awk? como en awk '{print $0 | "sort -nr" > "outfile" }' datafile, excepto con un delimitador de tabulación escapado enviado al comando de clasificación.
Merlin
11

Por defecto, el delimitador de campo no está en blanco a transición en blanco, por lo que la pestaña debería funcionar bien.

Sin embargo, las columnas están indexadas base 1 y base 0, por lo que probablemente desee

sort -k4nr file.txt

para ordenar file.txt por la columna 4 numéricamente en orden inverso. (Aunque los datos en la pregunta tienen incluso 5 campos, entonces el último campo sería el índice 5).

laalto
fuente
44
Esto solo funcionará si el número de caracteres de espacio entre los campos separados por tabulaciones es el mismo para todas las líneas de entrada.
Lars Haugseth
5

Debe colocar un carácter de tabulación real después de -t \ y para hacerlo en un shell, presione ctrl-v y luego el carácter de tabulación. La mayoría de los shells que he usado admiten este modo de entrada de tabulación literal.

Sin embargo, tenga cuidado, porque copiar y pegar desde otro lugar generalmente no conserva las pestañas.

Brian Carlsen
fuente
Esta es la mejor respuesta (la más portátil). emacs también le permite hacer eso en modo 'inserción entre comillas': C-q <tab>por ejemplo. Creo que también está ^Ven nano.
Wyatt8740
3

La solución $ no funcionó para mí. Sin embargo, al poner realmente el carácter de tabulación en el comando hizo: sort -t '' -k2

Lloyd
fuente
1
Úselo <C-v><Tab>para insertar pestañas en caso de que la tecla de pestañas se use para completar automáticamente en su shell.
Júda Ronén
1
La cotización ANSI $'\t'funciona en ksh, zsh y bash. Bourne Shell no lo admite. Ver esta publicación: unix.stackexchange.com/a/371873/201820
codeforester
1

canalizarla a través de algo así awk '{ print print $1"\t"$2"\t"$3"\t"$4"\t"$5 }'. Esto cambiará los espacios a pestañas.

Michiel Buddingh
fuente
@MB: Necesito mantener el espacio intacto.
neversaint
1
Indudablemente, hay una forma más limpia de hacerlo, pero nada le impide pasarlo por awk, cambiar los espacios a pestañas, ordenar los datos y luego volver a pasarlo por awk, volviendo a cambiar las pestañas a espacios.
Michiel Buddingh
1
Esto no funcionará si hay una combinación de pestañas y espacios que desea conservar.
James Thompson
1

En general, mantener datos como este no es una gran cosa si se puede evitar, porque la gente siempre confunde las pestañas y los espacios.

Resolver su problema es muy sencillo en un lenguaje de script como Perl, Python o Ruby. Aquí hay un código de ejemplo:

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

Quería una solución para Gnu sort en Windows, pero ninguna de las soluciones anteriores funcionó para mí en la línea de comandos.

Usando la pista de Lloyd, el siguiente archivo por lotes (.bat) funcionó para mí.

Escriba el carácter de tabulación dentro de las comillas dobles.

C:\>cat foo.bat

sort -k3 -t"    " tabfile.txt
Lawrence Noronha
fuente
1
Sí, el truco aquí es ponerlo en un archivo .bat, de lo contrario no funcionará
Carlos Rendon
1

Estaba teniendo este problema con sort en cygwin en un shell bash cuando usaba 'general-numeric-sort'. Si especifiqué -t$'\t' -kFg, donde F es el número de campo, no funcionó, pero cuando especifiqué ambos -t$'\t'y -kF,Fg(por ejemplo, -k7,7gpara el séptimo campo) funcionó. -kF,Fgsin el -t$'\t'no funcionó.

Danny
fuente
0

Si quiere hacerlo más fácil con solo pestañas, reemplace los espacios con pestañas:

tr " " "\t" < <file> | sort <options>
El gato no divertido
fuente
Mi tr no lee archivos, solo transmite XD. usage: tr [-Ccsu] string1 string2
The Unfun Cat
1
tr string1 string2 <some-file. Todo puede leer un archivo siempre que pueda leer stdin.
Randal Schwartz
0

La respuesta de Lars Haugseth solo funcionó desde la línea de comandos para mí, donde da este error si se ejecuta desde un script de shell:

ordenar: pestaña de varios caracteres '$ \ t'

La solución si está codificada en un script de shell si alguien está mirando es

sort -t'    '

el carácter de tabulación está entre comillas.

poderoso y débil codificador
fuente