Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

bash: oneliner to convert hex numbers in output to decimals

Does anyone know of a oneliner into which some output can be piped into in bash, to match and convert all occurrences of hexadecimal numbers and leave all other text untouched?

  • maybe match rather arbitrary output which could be a hexadecimal shall somehow converted through a regexp, i.e. /(0x)?[0-9a-fA-F]{5,}/
  • a leading 0x shall not be neccessary, but also be handled properly
  • there can be false-positives, if not specifying a minimum length of the numbers, but that should not be an issue
  • the goal is to find solution which can be used with as much possible outputs having hex numbers in them

It should work on output like:

ssg sjas # cat /proc/net/stat/arp_cache | column -t 
entries   allocs    destroys  hash_grows  lookups   hits      res_failed  rcv_probes_mcast  rcv_probes_ucast  periodic_gc_runs  forced_gc_runs  unresolved_discards  table_fulls
0000000d  00000006  00000004  00000000    0000c3b9  0000c35e  00000000    00000000          00000000          0000965b          00000000        00000000             00000000
0000000d  0000000d  00000004  00000001    00000000  00000000  00000000    00000000          00000000          000007cd          00000000        00000000             00000000
0000000d  00000008  00000008  00000001    00000000  00000000  00000000    00000000          00000000          000006e0          00000000        00000000             00000000
0000000d  0000000a  00000008  00000000    00000000  00000000  00000002    00000000          00000000          00000704          00000000        00000000             00000000

Most other questions on stackoverflow only tackle the issue of how to convert single numbers between number systems, only do the conversion for a specified column or completely kill the formatting being present in the input.

Desired output should look like: (column -t is there anyway, it really just need to replace the hex values it can find, and adding leading zeroes to a printf statement is also not a problem)

ssg sjas # cat /proc/net/stat/arp_cache | perl -pe 's/(?:0x)?[0-9a-f]{5,}/hex($&)/ge' | column -t
entries  allocs  destroys  hash_grows  lookups  hits   res_failed  rcv_probes_mcast  rcv_probes_ucast  periodic_gc_runs  forced_gc_runs  unresolved_discards  table_fulls
13       6       4         0           50105    50014  0           0                 0                 38491             0               0                    0
13       13      4         1           0        0      0           0                 0                 1997              0               0                    0
13       8       8         1           0        0      0           0                 0                 1760              0               0                    0
13       10      8         0           0        0      2           0                 0                 1796              0               0                    0

I could not find a short viable/reliable solution via sed/awk/perl in the last two hours, so I came here for help.

like image 664
sjas Avatar asked Jan 26 '26 10:01

sjas


2 Answers

perl using e flag to substitution

perl -pe 's/(0x)?[0-9a-f]{5,}/hex $&/ge' file | column -t
like image 104
123 Avatar answered Jan 29 '26 00:01

123


perl with the autosplit switch:

perl -anE'say join " ", map {/(?:0x)?([0-9a-f]{5,})/i ? hex $1 : $_} @F' file | column -t

The -n switch provides an implicit loop over the lines of the file.

The -E switch makes available optional features like the say command (useful to print something with an automatic carriage return). -E does also the same thing that the -e switch that executes the code given in parameter (instead of looking for a file to launch).

The -a switch (autosplit) splits each line on whitespace and populates the @F array with the parts (like awk does).

map { } @F processes each elements of @F and returns a new array.

/(?:0x)?([0-9a-f]{5,})/i ? hex($1) : $_ uses the ternary operator condition ? true : false. When the pattern matches it returns the converted capture group 1, when it doesn't the original part.

Note that Perl is a language that takes account of the context. $_ inside the map {} refers to a @F item, and /(?:0x)?([0-9a-f]{5,})/i is the short version for $_ =~ /(?:0x)?([0-9a-f]{5,})/i. (outside of the map {} $_ is the current line)

like image 34
Casimir et Hippolyte Avatar answered Jan 29 '26 01:01

Casimir et Hippolyte