Matt
Matt

Reputation: 153

Breaking down a long string and then converting hex to decimal

From another output, I have a long string:

00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000033B2E3C9FD0803CE8000000000000000000000000000000000000000000000D610B7305BB52FC30A0000000000000000000000000000000AF298D050E4395D69670B12B7F410000000000000000000000000000000000000000000000000000000000000000000000000000

which needs to be broken down into 64 character parts:

0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000033B2E3C9FD0803CE8000000
000000000000000000000000000000000000000D610B7305BB52FC30A0000000
000000000000000000000000AF298D050E4395D69670B12B7F41000000000000
0000000000000000000000000000000000000000000000000000000000000000

and then each line needs to be converted from hex to decimal with something like echo "obase=10; ibase=16; $hexNum" | bc

the hex part is easily solved. I suspect that an "awk" manipulation of the long string can break it down into 5 variable.. to which the above bc command can convert to decimal.

Upvotes: 1

Views: 130

Answers (4)

Matt
Matt

Reputation: 153

In the end, I set the string to a variable (dc) then

line1=${dc:1:64}
line2=${dc:65:64}
line3=${dc:129:64}
line4=${dc:193:64}
line5=${dc:257:64}

Upvotes: 0

David C. Rankin
David C. Rankin

Reputation: 84551

Another way is using read -n 64 ... to read 64 characters at a time, e.g.

while read -n 64 line && [ "${#line}" -eq 64 ]; do
    echo $line
    echo "value $(bc <<< "obase=10; ibase=16; $line")"
done

(note: the second test [ "${#line}" -eq 64 ] is only necessary if there is the possibility of the long string of numbers is terminated by a '\n' or other extraneous characters)

You would either pipe the long string to the snippet above, or you can redirect the string to the loop. For example, with your long input in the file string, you could do:

$ while read -n 64 line && [ "${#line}" -eq 64 ]; do
    echo $line
    echo "value $(bc <<< "obase=10; ibase=16; $line")"
done < string
0000000000000000000000000000000000000000000000000000000000000000
value: 0
0000000000000000000000000000000000000000033B2E3C9FD0803CE8000000
value: 1000000000000000000000000000
000000000000000000000000000000000000000D610B7305BB52FC30A0000000
value: 1060000000000000000000000000000
000000000000000000000000AF298D050E4395D69670B12B7F41000000000000
value: 1000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
value: 0

Note, the converted value of each 64-character string follows the "value: = " prefix provided below each 64-character line. You can adjust the output to meet your needs.

Upvotes: 1

karakfa
karakfa

Reputation: 67467

another solution

$ fold -w64 file | awk '{print strtonum("0x"$1)}'

0
1000000000000000013287555072
1060000000000000004189203726336
1000000000000000043845843045076197354634048000000
0

Upvotes: 3

glenn jackman
glenn jackman

Reputation: 246774

Here's one way:

input='00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000033B2E3C9FD0803CE8000000000000000000000000000000000000000000000D610B7305BB52FC30A0000000000000000000000000000000AF298D050E4395D69670B12B7F410000000000000000000000000000000000000000000000000000000000000000000000000000'
parts=() nums=()
while [[ -n $input ]]; do parts+=("${input:0:64}"); input=${input:64}; done
for h in "${parts[@]}"; do nums+=( $(echo "obase=10; ibase=16; $h" | bc) ); done

declare -p parts nums
declare -a parts=([0]="0000000000000000000000000000000000000000000000000000000000000000" [1]="0000000000000000000000000000000000000000033B2E3C9FD0803CE8000000" [2]="000000000000000000000000000000000000000D610B7305BB52FC30A0000000" [3]="000000000000000000000000AF298D050E4395D69670B12B7F41000000000000" [4]="0000000000000000000000000000000000000000000000000000000000000000")
declare -a nums=([0]="0" [1]="1000000000000000000000000000" [2]="1060000000000000000000000000000" [3]="1000000000000000000000000000000000000000000000000" [4]="0")

If you don't need to hold on to the 64-digit hex numbers, one loop is enough:

nums=()
for ((i=0; i<${#input}; i+=64)); do
    nums+=( $(bc <<< "obase=10; ibase=16; ${input:i:64}") )
done

Upvotes: 0

Related Questions