bc does not completely convert long hexadecimal numbers

248 views Asked by At

I am using bc to convert a long hex vectors to binary. It does not work for the following code example in my awk script:

#!/bin/awk -f

cmd = "bc <<< \"ibase=16;obase=2;"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"\""

result = ((cmd | getline binary_vector) > 0 ? binary_vector : -1)
close(cmd)
print "conversion result: " result

I get the following as output:

conversion result: 11111111111111111111111111111111111111111111111111111111111111111111\

This is not the complete result. bc does not convert the whole string and truncates in between with a "\". How can I convert the whole hexadecimal number?

2

There are 2 answers

5
valar_m On BEST ANSWER

The following command makes bc return a binary string of 1000 characters in one line.

cmd = "BC_LINE_LENGTH=1000 bc <<< \"ibas ...\"
0
n0741337 On

Here's an awk script I modified from a previous answer.

#!/usr/bin/awk -f

{
    cnt = split($0, a, FS)
    if( convertArrayBase(16, 2, a, cnt) > -1 ) {

        # use the array here
        for(i=1; i<=cnt; i++) {
            print a[i]
        }
    }
}

    # Destructively updates input array, converting numbers from ibase to obase
    #
    # @ibase:  ibase value for bc
    # @obase:  obase value for bc
    # @a:      a split() type associative array where keys are numeric
    # @cnt:    size of a ( number of fields )
    #
    # @return: -1 if there's a getline error, else cnt
    #
function convertArrayBase(ibase, obase, a, cnt,         i, b, c, cmd) {

    cmd = sprintf("echo \"ibase=%d;obase=%d", ibase, obase)
    for(i=1; i<=cnt; i++ ) {
        cmd = cmd ";" a[i]
    }
    cmd = cmd "\" | bc"

    i = 0 # reset i
    while( (cmd | getline b) > 0 ) {
        # if the return from bc is long, check for "\$" and build up c
        if( b ~ /\\$/ ) {
            sub(/\\/, "", b)
            c = c b
            continue;
        }
        a[++i] = c ? c b : b
        c = ""
    }
    close( cmd )
    return i==cnt ? cnt : -1
}

when the script is called awko and chmod +x awko it can be run like:

$ echo "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" | ./awko
111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111

The script attempts to convert the base of all the fields in a record, so the following also works:

$ echo "A B C D E F" | ./awko
1010
1011
1100
1101
1110
1111

Notice that the record's fields are output as separate lines. Instead of echo, an input file can be given to the script.