2

I'm trying to convert a 32 character long hex string (eg: A41EB86E184207262C12F66E7C480577) to binary. I'm using:

echo "ibase=16; obase=2; $line" | bc

but its including an unnecessary \ in-between which is not letting me perform any bit operations on the result.

An example output that I got is:

10100100000111101011100001101110000110000100001000000111001001100010\
110000010010111101100110111001111100010010000000010101110111

Notice the \ in the end of the first line.

What can I do to avoid it?

paxdiablo
  • 854,327
  • 234
  • 1,573
  • 1,953
gp_xps
  • 639
  • 1
  • 8
  • 12

1 Answers1

4

If you have a modern enough bc, you can set BC_LINE_LENGTH to zero to disable wrapping:

pax> echo "ibase=16;
...>       obase=2;
...>       A41EB86E184207262C12F66E7C480577" | BC_LINE_LENGTH=0 bc

This output your number on a single line.

1010010000011110101110000110111000011000010000100000011100100110001011000001...

I tend to have that in my .profile (or .bashrc, I can't remember off the top of my head) since I like that to be the default:

export BC_LINE_LENGTH=0

From the manpage:

BC_LINE_LENGTH: This should be an integer specifying the number of characters in an output line for numbers. This includes the backslash and newline characters for long numbers. As an extension, the value of zero disables the multi-line feature. Any other value of this variable that is less than 3 sets the line length to 70.

If your bc doesn't support the "0 means disable" extension, you can also set it ridiculously high:

export BC_LINE_LENGTH=9999

If your bc is "challenged" in that it doesn't allow BC_LINE_LENGTH at all, you may need to revert to post-processing of the output, such as using tr to get rid of newlines and backslashes:

pax> echo "ibase=16;obase=2;A41EB86E184207262C12F66E7C480577" | bc | tr -d '\\\n'
paxdiablo
  • 854,327
  • 234
  • 1,573
  • 1,953
  • would you also know how to prevent automatic stripping of trailing zeros? – gp_xps Sep 28 '12 at 03:45
  • @user1355848, I'm not aware there _is_ stripping of trailing zeros. If you enter `80` into your hex2bin converter, you get `10000000`. All the trailing zeros are there. – paxdiablo Sep 28 '12 at 03:48
  • 1
    BC_LINE_LENGTH is not mentioned on the POSIX specification for [`bc`](http://pubs.opengroup.org/onlinepubs/9699919799/utilities/bc.html). However, POSIX does say: _Very large numbers shall be split across lines with 70 characters per line in the POSIX locale; other locales may split at different character boundaries. Lines that are continued shall end with a ``._ It should be fairly easy to wrap lines ending with backslash-newline (`sed` etc). And why not set the line length to zero to disable the wrapping? – Jonathan Leffler Sep 28 '12 at 03:52
  • @Jonathan, good point though strangely, the line length still works with gnu-bc in POSIXLY_CORRECT mode. So I'll add another option for when that behaviour isn't available (and change it to use 0 rather than 9999). – paxdiablo Sep 28 '12 at 04:02
  • Thanks for your replys :) Im sorry. I meant the zeroes in the beginning. Not the trailer ones ( as that might change the value) If the first character was 4, it is converted to 100 instead of 0100 Any work around? – gp_xps Sep 28 '12 at 04:03
  • @user1355848, I'm not aware that `bc` itself will do that, you may need post-processing to adjust the length. You should ask _another_ question for that so it gets the proper exposure, rather than just Jon and me by the looks of it :-) – paxdiablo Sep 28 '12 at 04:05
  • AFAIK, `POSIXLY_CORRECT` only affects the behaviour of the `getopt()` function, suppressing the normal GNU 'permute arguments' behaviour. It may also affect `getopt_long()`. – Jonathan Leffler Sep 28 '12 at 04:19