使用 coreutils sort
,如何按十六进制值(字段)进行数字排序?我期待着类似的事情
sort -k3,3x file_to_sort
然而,这样的情况x
并不存在。
编辑:到目前为止我想出的最佳解决方案是:
{ echo ibase=16; cut -d' ' -f3 file_to_sort; } |
bc | paste -d: - file_to_sort | sort -t: -k1,1n | cut -d: -f2-
其中cut -d' ' -f3
隔离搜索字段(当然-k3,3
,这可能会有所不同),并bc
转换为十进制(需要大写十六进制,没有0x
前缀,与我的情况匹配)。然后我连接、排序和拆分列。
最小样本输入:
5 hhf 25
3 ezh ae
1 hdh d12
2 ukr 9f
4 jjk 7
预期输出(按hex
第三列排序的文件):
4 jjk 7
5 hhf 25
2 ukr 9f
3 ezh ae
1 hdh d12
答案1
我使用这个示例数据:
1 hdh d12
2 ukr 9f
3 ezh ae
4 jjk 7
5 hhf 25
这个想法是使用十进制形式的排序字段创建该数据的新版本。即awk
1 对其进行转换,将其添加到每一行的前面,对结果进行排序,最后一步删除添加的字段:
awk '{val="0x" $3; sub("^0x0x","0x",val); print strtonum(val),$0 ;}' file |
sort -n |
sed 's/^[^ ]* //'
其结果是这样的输出:
4 jjk 7
5 hhf 25
2 ukr 9f
3 ezh ae
1 hdh d12
1 这里假设 GNUawk
的strtonum()
功能。
答案2
解决方案perl
:
$ perl -anle '
push @h, [$F[-1],$_];
END {
print for map { $_->[0] }
sort { $a->[1] <=> $b->[1] }
map { [$_->[1],hex($_->[0])] } @h;
}
' file
4 jjk 7
5 hhf 25
2 ukr 9f
3 ezh ae
1 hdh d12
解释
在处理文件时,我们创建一个数组的数组
@h
,它的每个元素都是一个数组引用[$F[-1],$_]
,第一个元素是要比较的十六进制值,第二个元素是整行。在
END
块中,我们使用施瓦茨变换:使用 的每个元素
@h
,创建一个匿名数组,包含整行($_->[1]
每个数组 ref 中的第二个元素@h
)和要比较的十六进制值hex($_->[0])]
根据十六进制值对上面的数组进行排序
$a->[1] <=> $b->[1]
获取排序数组中每个数组 ref 的第一个元素,
map { $_->[0] }
然后打印结果。
更新
根据@Joseph R 的建议:
$ perl -anle '
push @h, [hex($F[-1]),$_];
END {
print $_->[1] for
sort { $a->[0] <=> $b->[0] } @h;
}
' file
更新2
阅读 Stefan 的评论后,不使用 Schwartzian 变换:
$ perl -e '
print sort {hex((split(/\s+/,$a))[-1]) <=> hex((split(/\s+/,$b))[-1])} <>;
' file
4 jjk 7
5 hhf 25
2 ukr 9f
3 ezh ae
1 hdh d12
答案3
输入
$ cat /tmp/input
0x45 aaa 333
0x50 dd 33
0x4 bbbb 444
0x456 cc 22
0x5 eee 1111
排序一个班轮
$ gawk --non-decimal-data '{ dec = sprintf("%d", $1); print dec " " $0 }' /tmp/input | sort -n -k 1 | cut -f2- -d' '
0x4 bbbb 444
0x5 eee 1111
0x45 aaa 333
0x50 dd 33
0x456 cc 22
逐步排序
步骤 1:添加新的第一列,其中包含十六进制数的十进制表示形式。
$ gawk --non-decimal-data '{ dec = sprintf("%d", $1); print dec " " $0 }' /tmp/input
69 0x45 aaa 333
80 0x50 dd 33
4 0x4 bbbb 444
1110 0x456 cc 22
5 0x5 eee 1111
步骤 2:按数字对第一个字段中的行进行排序。
$ gawk --non-decimal-data '{ dec = sprintf("%d", $1); print dec " " $0 }' /tmp/input | sort -n -k 1
4 0x4 bbbb 444
5 0x5 eee 1111
69 0x45 aaa 333
80 0x50 dd 33
1110 0x456 cc 22
步骤 3:删除第一列。
$ gawk --non-decimal-data '{ dec = sprintf("%d", $1); print dec " " $0 }' /tmp/input | sort -n -k 1 | cut -f2- -d' '
0x4 bbbb 444
0x5 eee 1111
0x45 aaa 333
0x50 dd 33
0x456 cc 22
答案4
sort -g
可以对十六进制值进行排序。需要注意的是,它需要0x
前缀。
awk '{ $3 = "0x" $3; print }' sample.txt |
sort -g -k3 |
awk '{ $3 = gensub(/^0x/, "", 1, $3); print }'
- 添加
0x
到第三列之前 - 使用通用数字排序选项按第三列排序
0x
从第三列删除