我正在尝试使用对一些数据进行排序sort
。我注意到它是按数字而不是数字排序,所以我添加了标志-n
。不过,它似乎只是对第一个字段进行数字排序。按字段分解它是一个问题,因为这些行具有不同数量的字段(坦率地说,我无法理解它的行为)。这是我正在使用的一些足够接近的示例数据:
echo -e "b b 1\n23 44\nb 3\na 7\nb b 2\na 1\nb a 10\nb b 10\nb 1\nb a 1\n18 2\nb 10\n18 15\nb a 2\n23 9\nb 2" | sort -n
Input Want Expect? sort -n -n -k1,1 -k2,2 -k3,3 -k4,4…
b b 1 8 2 a 1 23 44 a 1 b a 1
23 44 8 15 a 7 23 9 a 7 b a 10
b 3 23 9 b a 1 8 15 b 1 b a 2
a 7 23 44 b a 2 8 2 b 10 b b 1
b b 2 a 1 b a 10 a 1 b 2 b b 10
a 1 a 7 b b 1 a 7 b 3 b b 2
b a 10 b 1 b b 2 b 1 b a 1 a 1
b b 10 b 2 b b 10 b 10 b a 10 b 1
b 1 b 3 b 1 b 2 b a 2 b 2
b a 1 b 10 b 2 b 3 b b 1 b 3
8 2 b a 1 b 3 b a 1 b b 10 a 7
b 10 b a 2 b 10 b a 10 b b 2 b 10
8 15 b a 10 8 2 b a 2 8 15 8 2
b a 2 b b 1 8 15 b b 1 8 2 8 15
23 9 b b 2 23 9 b b 10 23 44 23 9
b 2 b b 10 23 44 b b 2 23 9 23 44
理想情况下,我希望它能够在具有 GNU coreutils sort 5.93 的机器上运行。我想用简单的unix工具来处理它;我不想把问题交给 perl 等。我希望有一个等价的[想象]sort --numeric-sort --all-fields --actually-work
答案1
我认为你的问题是你不明白sort
在做什么。基本排序基于 ASCII 字符值,其中数字在大写字母之前,数字在小写字母之前:'1' == 49、'A' == 65、'a' = 97。这解释了该sort
列,其中数字如 '23 ' 排序在 '8 ' 之前,即 'b b' 之前:'2' 的 ASCII 值为 50,'8' 的 ASCII 值为 56,'b' 为 98。
当按数字排序 ( sort -n
) 时,非数字条目按常规方法排序,但与数字相比时解释为 0,例如 23 或 8;但由于该值被视为数字而不是字符值,因此“8”位于“23”之前。因此,字母条目将排序在数字条目之前。
最好的办法是标准化数据,使每列具有相同类型的值:要么都是数字,要么都是字母数字,并适当排序。
在最后一列(按字段排序)中,它将首先对具有更多字段的条目进行排序,因为您明确指定了 4 个(或更多)字段。所以 (1,2,3) 将在 (1,2) 之前。如果没有该-k
选项,排序会将行作为一个整体考虑在内。
您可以阅读有关的更多信息信息 coreutils 排序页。
答案2
echo -e "b b 1\n23 44\nb 3\na 7\nb b 2\na 1\nb a 10\nb b 10\nb 1\nb a 1\n18 2\nb 10\n18 15\nb a 2\n23 9\nb 2" \
| sed -r 's/[a-z]/9999&/g' | sort -n -k1 -k2 -k3 | sed 's/9999//g'
18 2
18 15
23 9
23 44
a 1
b 1
b 2
b 3
a 7
b 10
b a 1
b b 1
b a 2
b b 2
b a 10
b b 10
这就是你想要的吗?如果是数字,则按数字排序,并将数字放在其他字符之前?
我在每个字符串前面加上一个大数字作为前缀,以便通过排序将字符串放在最后,并在最后删除大数字(9999)。
答案3
经过几年的发展,sort -V
onsort 8.26
产生了所需的输出:
$ echo -e "b b 1\n23 44\nb 3\na 7\nb b 2\na 1\nb a 10\nb b 10\nb 1\nb a 1\n8 2\nb 10\n8 15\nb a 2\n23 9\nb 2" \
| sort -V
8 2
8 15
23 9
23 44
a 1
a 7
b 1
b 2
b 3
b 10
b a 1
b a 2
b a 10
b b 1
b b 2
b b 10