6

I saw the following code in Bash shell Decimal to Binary conversion and I was wondering how it works? I tried googling with no avail.

D2B=({0..1}{0..1}{0..1}{0..1}{0..1}{0..1}{0..1}{0..1})

echo ${D2B[7]}

What does the code above do?

jww
  • 97,681
  • 90
  • 411
  • 885
  • Look up `brace expansion` and `bash arrays` – 123 Jun 24 '17 at 16:25
  • 5
    This creates an array with `00000000 00000001 00000010 ... 11111101 11111110 11111111` with [bash‘s brace](https://www.gnu.org/software/bash/manual/bash.html#Brace-Expansion) expansion. The position in array D2B represents its decimal value. – Cyrus Jun 24 '17 at 16:32
  • By the way, this is also possible `D2B=({0,1}{0,1}{0,1}{0,1}{0,1}{0,1}{0,1}{0,1})` – Cyrus Jun 24 '17 at 18:36
  • 1
    For clarification, in this case, the brace expansion has the effect of listing all 256 permutations that eight bits can have (ie. from 00000000 to 11111111). Because it is done inside parantheses the results are saved into an array, which is then assigned to the variable D2B. The echo command echos the seventh element of the array. Because the permutations are in order, the seventh element is 00000111, which is binary for the decimal number 7. To see all of the elements in the array use `echo "${D2B[@]}"` (double quotes are important). – Casey Apr 24 '18 at 10:44
  • Actually, I think that the seventh element is only equal to "7" if you choose to interpret the sequence generated by the brace expansion as big-endian. To bash it is just spitting out a predictable sequence of characters (not bits). It is just a happy coincidence that the way it expands the permutations is ordered when they are considered big-endian. I guess that if you used {1,0} they would be listed in reverse order, and if you used `tac` (ie. reverse cat) you could convert them to little-endian. But you still couldn't save this to a file as binary without further transformation. – Casey Apr 24 '18 at 11:10

2 Answers2

5

{N..M}, for integer literals N and M, generates the series of integers from N to M, inclusively, separated by spaces. This is called a "brace expansion", and is a bashism. As you can see, all brace expansions are done before adding spaces between them.

variable=({some expansion}) puts each of the expanded items in an array, and ${variable[index number]} extracts the value at that index. So your code effectively returns the number seven in binary string form.

l0b0
  • 55,365
  • 30
  • 138
  • 223
  • simple example to help understand: `a=({0..1}{2..3}); echo ${a[@]}`. The `echo` statement prints `a` for all indices. – Wolfson Jan 16 '23 at 19:35
2

Just as an additional hint: This construct is fairly generic as it works for any n-based numbering system up to n = 9. Octal as an example:

$ D2O=({0..7}{0..7}{0..7}{0..7})
$ echo ${D2O[7]}
0007
$ echo ${D2O[8]}
0010
$ echo ${D2O[668]}
1234
$ echo ${D2O[4095]}
7777

The leading zeros can be eliminated in the same fashion as explained at Bash shell Decimal to Binary conversion:

echo $((10#${D2O[7]}))
7
Ralph Kirchner
  • 331
  • 2
  • 2