使用 coreutils sort
,如何按十六进制值(字段)进行数字排序?我期待着类似的东西
sort -k3,3x file_to_sort
Run Code Online (Sandbox Code Playgroud)
然而,这样的x
情况并不存在。
编辑:到目前为止我想出的最佳解决方案是:
{ echo ibase=16; cut -d' ' -f3 file_to_sort; } |
bc | paste -d: - file_to_sort | sort -t: -k1,1n | cut -d: -f2-
Run Code Online (Sandbox Code Playgroud)
其中cut -d' ' -f3
隔离搜索字段(这是-k3,3
-这可能会有所不同,当然),和bc
不转换为十进制(需要大写十六进制,没有0x
前缀,匹配我的情况)。然后我加入、排序和拆分列。
最小样本输入:
5 hhf 25
3 ezh ae
1 hdh d12
2 ukr 9f
4 jjk 7
Run Code Online (Sandbox Code Playgroud)
预期输出(按hex
第三列排序的文件):
4 jjk 7
5 hhf 25
2 ukr 9f
3 ezh ae
1 hdh d12
Run Code Online (Sandbox Code Playgroud)
我使用这个示例数据:
1 hdh d12
2 ukr 9f
3 ezh ae
4 jjk 7
5 hhf 25
Run Code Online (Sandbox Code Playgroud)
这个想法是使用十进制形式的排序字段创建此数据的新版本。即awk
转换它,将它添加到每一行,结果被排序,最后一步添加的字段被删除:
awk '{val="0x" $3; sub("^0x0x","0x",val); print strtonum(val),$0 ;}' file |
sort -n |
sed 's/^[^ ]* //'
Run Code Online (Sandbox Code Playgroud)
这导致此输出:
4 jjk 7
5 hhf 25
2 ukr 9f
3 ezh ae
1 hdh d12
Run Code Online (Sandbox Code Playgroud)
解决方案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
Run Code Online (Sandbox Code Playgroud)
解释
在处理文件时,我们创建一个 array 数组@h
,它的每个元素都是一个数组引用[$F[-1],$_]
,第一个元素是要比较的十六进制值,第二个元素是整行。
在END
块中,我们使用Schwartzian 变换:
使用 的每个元素@h
,创建一个匿名数组,包含整行($_->[1]
每个数组 ref in 的第二个元素@h
)和要比较的十六进制值hex($_->[0])]
根据十六进制值在数组上方排序 $a->[1] <=> $b->[1]
获取排序数组中每个数组 ref 的第一个元素,map { $_->[0] }
然后打印结果。
更新
根据@Joseph R 的建议,不使用 Schwartzian 变换:
$ perl -anle '
push @h, [hex($F[-1]),$_];
END {
print $_->[1] for
sort { $a->[0] <=> $b->[0] } @h;
}
' file
Run Code Online (Sandbox Code Playgroud)
更新 2
阅读 stefan 的评论后,我认为这可以称为direct
:
$ 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
Run Code Online (Sandbox Code Playgroud)