Is it Possible to sort a list of hexadecimal numbers using "sort" command?

Hello Everybody :slight_smile: !!!. i have question in mind, is it possible to sort a list of hexadecimal numbers using "sort" command?

From the book "UNIX power tools By Shelley Powers, Jerry Peek"

There is no provision for sorting hexadecimal numbers

In this way we can sort

$ cat hexanumbers.txt
3E80
3EF8
460
$ cat testfile.sh
#!/bin/ksh
for i in `cat hexanumbers.txt | awk '{ print "16#"$0}'`
do
typeset -i10 i
echo $i >> decimals_list.txt
done
for i in `cat decimals_list.txt | sort`
do
        echo "obase=16;$i" | bc
done
rm decimals_list.txt 
$ ksh testfile.sh
460
3E80
3EF8
$
1 Like

Hi.

The utility msort might be found in your repository, or, failing that, at MSORT

Best wishes ... cheers, drl

based on jayan_jay's, here's a bash script :

$ cat hexanumbers.txt
3E80
3EF8
460
$ while read hexnum; do array[16#$hexnum]="$hexnum"; done < hexanumbers.txt 
$ printf '%s\n' "${array[@]}"
460
3E80
3EF8
awk '{printf("%050s\t%s\n", toupper($0), $0)}' hex-data | LC_COLLATE=C sort -k1,1 | cut -f2

If you take a look at the C/POSIX collation sequence, you'll see that the sequences A-F and a-f both sort after 0-9 in the POSIX/C locale. So long as the hex numbers do not mix case and are of the same length, the string collation sequence is congruent to a hex digits sequence.

LC_COLLATE Category in the POSIX Locale

If you have a list of hex numbers, you can decorate them with a column of zero-padded, case-folded numbers, sort on that column, then output the original numbers.

$ cat hex-data
3e80
3EF8
460
$ awk '{printf("%050s\t%s\n", toupper($0), $0)}' hex-data | LC_COLLATE=C sort -k1,1 | cut -f2
460
3e80
3EF8

Regards,
Alister

IMO, if the OP really have such numbers he should just normalize them. And there is no need to undecorate them back.

cat NUMS |  xargs printf "%4s\n" | tr 'a-z ' 'A-Z0' | sort

(It is "useful use" of cat).
Or with awk if there are several numbers on lines:

awk '{
  for ( i = 1; i <= NF; i++ ) {
    s = sprintf("%04s", $i)
    gsub(" ", "0", s)
    printf s " "
  }
  print ""
}' NUMS | tr a-z A-Z | sort 

Use 2 or 8 for bytes and 32-bit words.

Here's how it can be done with perl...

perl -e '@a=(0x3E80,0x3EF8,0x460);@r=sort {$a <=> $b} @a;printf("%X\n" x @r,@r);'

Thanks Drl i will give it a shot.......:):slight_smile:

Hi.

In some situations, a string representing a hex number may need an adjustment to be recognized, such as adding a prefix "0x" -- that's what you would need to do with msort to get it to recognize hex numbers. If one has a file of "plain" hex numbers, then one solution to use the standard sort might be to do such an adjustment if necessary, add a column to the line in decimal, then sort that intermediate file, and finally eliminate the first column, say with cut.

Here's is a longish script that uses a perl script to do some of that work. The data file is a made-up report of manufacturers in countries that create widgets with a number of employees, all with fictitious hex numbers:

#!/usr/bin/env bash

# @(#) s4	Demonstrate sort of hex column.

# Utility functions: print-as-echo, print-line-with-visual-space, debug.
# export PATH="/usr/local/bin:/usr/bin:/bin"
pe() { for _i;do printf "%s" "$_i";done; printf "\n"; }
pl() { pe;pe "-----" ;pe "$*"; }
db() { ( printf " db, ";for _i;do printf "%s" "$_i";done;printf "\n" ) >&2 ; }
db() { : ; }
C=$HOME/bin/context && [ -f $C ] && $C perl sort cut

COL=${1-2}
FILE=data4

pl " Input data file $FILE (aligned):"
pe " Country widgets manufacturers employees"
pe
align $FILE

pl " Results, sorted on column $COL, aligned:"
./p1 $COL < $FILE |
tee f1 |
sort -k1,1n |
tee f2 |
cut -f2- |
tee f3 |
align

COL=4
pl " Results, sorted on column $COL, aligned:"
./p1 $COL < $FILE |
tee f1 |
sort -k1,1n |
tee f2 |
cut -f2- |
tee f3 |
align

pl " Addendum, perl script \"p1\" to add the decimal equivalent:"
cat p1

exit 0

producing:

% ./s4

Environment: LC_ALL = C, LANG = C
(Versions displayed with local utility "version")
OS, ker|rel, machine: Linux, 2.6.26-2-amd64, x86_64
Distribution        : Debian GNU/Linux 5.0.8 (lenny) 
GNU bash 3.2.39
perl 5.10.0
sort (GNU coreutils) 6.10
cut (GNU coreutils) 6.10

-----
 Input data file data4 (aligned):
 Country widgets manufacturers employees

Belarus		f59	26	3a
Gibraltar	b26	2b	25
Iceland		aaf	23	2e
Ireland		426	29	29
Netherlands	d4d	17	5a
Slovakia	91d	2c	42
Spain		556	31	2d
Switzerland	49a	2e	54
Turkey		9e5	15	46
Ukraine		1154	26	4a

-----
 Results, sorted on column 2, aligned:
Ireland		426	29	29
Switzerland	49a	2e	54
Spain		556	31	2d
Slovakia	91d	2c	42
Turkey		9e5	15	46
Iceland		aaf	23	2e
Gibraltar	b26	2b	25
Netherlands	d4d	17	5a
Belarus		f59	26	3a
Ukraine		1154	26	4a

-----
 Results, sorted on column 4, aligned:
Gibraltar	b26	2b	25
Ireland		426	29	29
Spain		556	31	2d
Iceland		aaf	23	2e
Belarus		f59	26	3a
Slovakia	91d	2c	42
Turkey		9e5	15	46
Ukraine		1154	26	4a
Switzerland	49a	2e	54
Netherlands	d4d	17	5a

-----
 Addendum, perl script "p1" to add the decimal equivalent:
#!/usr/bin/env perl

# @(#) p1	Demonstrate extraction of hex column, convert to decimal.

use warnings;
use strict;

my ($debug);
$debug = 1;
$debug = 0;

# Select column (beginning from 0, allow user to specify from 1.
my ($col) = shift || "2";

# Set separator.
my ($sep) = "\t";

# Walk through file.
while (<>) {
  chomp;
  my (@a)  = split /$sep/;
  my ($t1) = $a[ $col - 1 ];
  print " hex column is $col, content before is :$t1:\n" if $debug;
  $t1 =~ s/\s*//g;
  print " hex column is $col, content after  is :$t1:\n" if $debug;
  print hex($t1), "$sep$_\n";
}

exit(0);

The shell script allows a column number to passed in to select the column to be sorted.

The files f1, f2, etc., allow the viewing of intermediate results; they can be eliminated for production use.

This also uses align so that the columns are readable, see Read an ascii as cell-tabulated form for more information about that ... cheers, drl