8

I have the bash line:

expr substr $SUPERBLOCK 64 8

Which is return to me string line:

00080000

I know that this is, actually, a 0x00080000 in little-endian. Is there a way to create integer-variable from it in bash in big-endian like 0x80000?

jesse_b
  • 35,934
  • 12
  • 91
  • 140
DenisNovac
  • 285
  • 2
  • 3
  • 10

2 Answers2

9

Probably a better way to do this but I've come up with this solution which converts the number to decimal and then back to hex (and manually adds the 0x):

printf '0x%x\n' "$((16#00080000))"

Which you could write as:

printf '0x%x\n' "$((16#$(expr substr "$SUPERBLOCK" 64 8)))"
jesse_b
  • 35,934
  • 12
  • 91
  • 140
  • Thank you! I actually added |rev inside to convert to big-endian: printf "$((16#$(expr substr $SUPERBLOCK 64 8|rev)))" – DenisNovac Mar 18 '19 at 18:53
  • 5
    @DenisNovac I'm not sure if you use big/little endian correctly (maybe you have something else on mind, but I'm doing some assembly programming for fun, so for me endianness is per bytes), but 0x12345678 is in other endianness 0x78563412, not 0x87654321. (and the value in your question `00080000` is after byte swap `00000800`, i.e. 2048 decimal) – Ped7g Mar 18 '19 at 18:55
  • Oh, you are right. I just got the right answer by wrong way. I am rewriting some code from python to bash, so i know all answers before i got them. – DenisNovac Mar 18 '19 at 19:01
  • @DenisNovac: You didn't have the right answer FYI. 0x8000 was originally in your question which is not the same as 0x80000 or 0x00080000 – jesse_b Mar 18 '19 at 19:07
  • Yes, but i needed to get exactly 0x8000, so i've made mistake somewhere before. This is offset or something. – DenisNovac Mar 18 '19 at 19:12
  • If you need 0x8000 you are also looking to change the value of the number completely? – jesse_b Mar 18 '19 at 19:12
  • 0x00080000 = 524288, 0x8000 = 32768 – jesse_b Mar 18 '19 at 19:14
  • Actually, that was an offset mistake. To read the right number i need to write "expr substr $SUPERBLOCK 65 8" and this is 0x00800000, which is, in big-endian, gives 0x8000 (i checked it on more specific field such as checksum, where no zeros around). But now i need a way to reverse string by two chars pairs or somehow convert between big-endian and little-endian. – DenisNovac Mar 18 '19 at 19:23
  • So this is how i do it for 8 bytes hex number: v="$(expr substr $SUPERBLOCK 65 8)"\ s="${v:6:2}${v:4:2}${v:2:2}${v:0:2}"\ BLOCKS_PER_GROUP="$((16#$s))" – DenisNovac Mar 18 '19 at 19:47
5

There are two more or less standard (and ancient) command-line unix tools that offer very easy ways to convert numbers between different bases:

$ { echo '16'; echo i; echo 00080000; echo p; } | dc
524288
$ { echo 'ibase=16'; echo 00080000; } | bc  
524288

For normal human use I very much prefer bc, but when writing a program that generates code, especially from a parser of some sort, a stack-based tool like dc may be easier to deal with (and indeed the original version of bc was a front-end parser for dc).

Greg A. Woods
  • 793
  • 5
  • 9