对以制表符分隔的文件进行排序

我有一份数据,格式如下:

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'

正确的做法是什么?

这里是样本数据

202639 次浏览

通过类似awk '{ print print $1"\t"$2"\t"$3"\t"$4"\t"$5 }'的管道传递它。这将把空格改为制表符。

默认情况下,字段分隔符是非空白到空白的过渡,所以tab应该可以正常工作。

但是,列的索引以1和0为底,所以您可能希望

sort -k4nr file.txt

按第4列按数字倒序排序file.txt。(虽然问题中的数据甚至有5个字段,所以最后一个字段将是索引5。)

一般来说,如果可以避免的话,像这样保存数据并不是一件好事,因为人们总是混淆制表符和空格。

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

使用bash,这将达到目的:

$ sort -t$'\t' -k3 -nr file.txt
注意单引号字符串前面的美元符号。你可以读到 它在ANSI-C引用bash手册页的部分.

$的解决方案对我不起作用。 然而,通过实际将制表符本身放在命令中: 排序-t " -k2

我想在Windows上为Gnu排序提供一个解决方案,但是上面的解决方案都不能在命令行上为我工作。

使用Lloyd的线索,下面的批处理文件(.bat)对我有用。

在双引号内键入制表符。

C:\>cat foo.bat


sort -k3 -t"    " tabfile.txt

我在使用“通用数字排序”时,在bash shell中的cygwin排序遇到了这个问题。如果我指定-t$'\t' -kFg,其中F是字段号,它就不起作用,但当我同时指定-t$'\t'-kF,Fg(例如-k7,7g为第7个字段)时,它就起作用了。没有-t$'\t'-kF,Fg不能工作。

你需要在-t\后面加一个制表符,在shell中按下ctrl-v,然后再按制表符。我使用过的大多数shell都支持这种文字选项卡条目模式。

但是要注意,从另一个地方复制和粘贴通常不会保留制表符。

如果你想用制表符来简化操作,可以用制表符替换空格:

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

Lars Haugseth的答案只适用于我的命令行,如果从shell脚本执行,它会给出这个错误:

排序:多字符TAB ' $\t '

解决方案,如果它被编码在一个shell脚本,如果有人看

sort -t'    '

制表符位于引号之间。

sort -t "$(printf '\t')"适合我