Сортировка файла с разделителями табуляции

180

У меня есть данные в следующем формате:

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

Теперь я попытался отсортировать файл по последнему полю по убыванию. Я попробовал следующие команды, но они не были отсортированы, как мы ожидали.

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

Какой правильный способ сделать это?

Вот пример данных .

neversaint
источник

Ответы:

313

Используя bash , это поможет:

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

Обратите внимание на знак доллара перед строкой в ​​одинарных кавычках. Вы можете прочитать об этом в разделах цитирования ANSI-C на странице руководства bash .

Ларс Хаугсет
источник
2
Используйте '"'"' для использования внутри псевдонима.
Пабло А
Можете ли вы показать, как передать этот разделитель для сортировки в команде awk? как awk '{print $0 | "sort -nr" > "outfile" }' datafile, кроме как с помощью разделителя с экранированными табуляциями, отправляемого команде сортировки.
Мерлин
Используйте, -gа не -nесли вы хотите числовую сортировку. -nсломан.
Люк Хатчисон
11

По умолчанию разделитель поля является непустым переходом к пустому, поэтому вкладка должна работать очень хорошо.

Тем не менее, столбцы индексируются как база 1 и база 0, так что вы, вероятно, хотите

sort -k4nr file.txt

отсортировать файл file.txt по столбцу 4 в обратном порядке. (Хотя данные в вопросе имеют даже 5 полей, поэтому последнее поле будет индексом 5.)

laalto
источник
4
Это будет работать только в том случае, если количество пробелов между полями, разделенными табуляцией, одинаково для всех строк ввода.
Ларс Хаугсет
5

Вам нужно поместить фактический символ табуляции после -t \ и сделать это в оболочке, нажав Ctrl-V, а затем символ табуляции. Большинство оболочек, которые я использовал, поддерживают этот режим буквального ввода табуляции.

Однако будьте осторожны, потому что копирование и вставка из другого места обычно не сохраняет вкладки.

Брайан Карлсен
источник
Это лучший (самый переносимый) ответ. Emacs также позволяет вам делать это в режиме 'вставки в кавычки': C-q <tab>например. Я думаю, что это ^Vв нано.
Wyatt8740
3

Решение $ не сработало для меня. Однако, фактически поместив сам символ табуляции в команду, сделал: sort -t '' -k2

Lloyd
источник
1
Используйте <C-v><Tab>для вставки вкладки, если клавиша табуляции используется для автозаполнения в вашей оболочке.
Худа Ронен,
1
Цитирование ANSI $'\t'работает в ksh, zsh и bash. Оболочка Борна не поддерживает это. Смотрите это сообщение: unix.stackexchange.com/a/371873/201820
codeforester
1

труба через что-то вроде awk '{ print print $1"\t"$2"\t"$3"\t"$4"\t"$5 }'. Это изменит пробелы на вкладки.

Мичиэль Буддинг
источник
@MB: мне нужно сохранить пространство нетронутым.
неосвещенный
1
Несомненно, есть более чистый способ сделать это, но ничто не мешает вам передать его через awk, изменить пробелы на вкладки, отсортировать данные, а затем снова передать их через awk, превратив вкладки обратно в пробелы.
Michiel Buddingh
1
Это не будет работать, если есть смесь вкладок и пробелов, которые вы хотите сохранить.
Джеймс Томпсон
1

В общем, хранить подобные данные не очень хорошая вещь, если вы можете избежать этого, потому что люди всегда путают табуляции и пробелы.

Решение вашей проблемы очень просто на языке сценариев, таких как Perl, Python или Ruby. Вот пример кода:

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

Я хотел найти решение для сортировки Gnu в Windows, но ни одно из перечисленных выше решений не работало для меня в командной строке.

Используя подсказку Ллойда, следующий пакетный файл (.bat) работал для меня.

Введите символ табуляции в двойных кавычках.

C:\>cat foo.bat

sort -k3 -t"    " tabfile.txt
Лоуренс Норонья
источник
1
Да, хитрость здесь заключается в том, чтобы поместить его в файл .bat, иначе это не сработает
Карлос Рендон,
1

У меня была эта проблема с сортировкой в ​​cygwin в оболочке bash при использовании 'general-numeric-sort'. Если я указал -t$'\t' -kFg, где F - номер поля, это не сработало, но когда я указал оба -t$'\t'и -kF,Fg(например, -k7,7gдля 7-го поля), оно сработало. -kF,Fgбез -t$'\t'не работал.

Дэнни
источник
0

Если вы хотите упростить для себя только наличие вкладок, замените пробелы вкладками:

tr " " "\t" < <file> | sort <options>
Несчастный кот
источник
Мой тр не читает файлы, только потоки XD. usage: tr [-Ccsu] string1 string2
Несчастный кот
1
tr string1 string2 <some-file, Файл может читать каждый, если он умеет читать stdin.
Рэндал Шварц
0

Ответ Ларса Хаугсета работал только для меня из командной строки, где он выдает эту ошибку, если выполняется из сценария оболочки:

сортировка: многосимвольная вкладка '$ \ t'

Решение, если оно закодировано в сценарии оболочки, если кто-то ищет,

sort -t'    '

символ табуляции находится между кавычками.

mightyandweakcoder
источник