For work, I'm writing a Cygwin Bash script that must convert a hex string to packed binary format. At the present, I'm doing this with a C# program. But I would really like to do it inside the script, if possible. Is there a command that will do this? If not, is it feasible to do it with script programming?
For reference, I've included my C# program below. It was just something I wrote for quick testing, not as serious program. But it shows what I need done. I need the hex digits converted to binary (4 bits each), then packed two per byte.
using System;
using System.IO;
namespace HexAsciiToPackedBinary {
class Program {
static void Main(string[] args) {
if (args.Length != 2) {
Console.WriteLine("usage: ha2pb infile outfile");
return;
}
string infile = args[0];
string outfile = args[1];
byte[] allBytes = File.ReadAllBytes(infile);
byte[] packedBytes = new byte[allBytes.Length / 2];
for (int i = 0; i < allBytes.Length; i += 2) {
byte ubits = (byte)(GetVal(allBytes[i]) << 4);
byte lbits = GetVal(allBytes[i + 1]);
packedBytes[i/2] = (byte)(ubits | lbits);
}
File.WriteAllBytes(outfile, packedBytes);
}
static byte GetVal(byte b) {
if (b >= 0x30 && b <= 0x39) { // 0 - 9
return (byte)(b - 0x30);
}
if (b >= 0x61 && b <= 0x66) { // a - f
return (byte)(b - 0x61 + 10);
}
if (b >= 0x41 && b <= 0x46) { // A - F
return (byte)(b - 0x41 + 10);
}
Console.WriteLine("Bad char.");
return unchecked((byte)-1);
}
}
}
For work, I'm writing a Cygwin Bash script that must convert a hex string to packed binary format. At the present, I'm doing this with a C# program. But I would really like to do it inside the script, if possible. Is there a command that will do this? If not, is it feasible to do it with script programming?
For reference, I've included my C# program below. It was just something I wrote for quick testing, not as serious program. But it shows what I need done. I need the hex digits converted to binary (4 bits each), then packed two per byte.
using System;
using System.IO;
namespace HexAsciiToPackedBinary {
class Program {
static void Main(string[] args) {
if (args.Length != 2) {
Console.WriteLine("usage: ha2pb infile outfile");
return;
}
string infile = args[0];
string outfile = args[1];
byte[] allBytes = File.ReadAllBytes(infile);
byte[] packedBytes = new byte[allBytes.Length / 2];
for (int i = 0; i < allBytes.Length; i += 2) {
byte ubits = (byte)(GetVal(allBytes[i]) << 4);
byte lbits = GetVal(allBytes[i + 1]);
packedBytes[i/2] = (byte)(ubits | lbits);
}
File.WriteAllBytes(outfile, packedBytes);
}
static byte GetVal(byte b) {
if (b >= 0x30 && b <= 0x39) { // 0 - 9
return (byte)(b - 0x30);
}
if (b >= 0x61 && b <= 0x66) { // a - f
return (byte)(b - 0x61 + 10);
}
if (b >= 0x41 && b <= 0x46) { // A - F
return (byte)(b - 0x41 + 10);
}
Console.WriteLine("Bad char.");
return unchecked((byte)-1);
}
}
}
Share
Improve this question
edited 10 hours ago
tshiono
22k2 gold badges17 silver badges25 bronze badges
asked 12 hours ago
RickyBobbyRickyBobby
514 bronze badges
4
|
1 Answer
Reset to default 1If the hex string comes from a bash variable:
$ str='415A41'
$ for((i=0; i<${#str}; i+=2)); do printf "\x${str:i:2}"; done
AZA
If it comes from a text file:
$ { echo "414141"; echo "5A5A5A"; } > file.hex
$ mapfile -t a < file.hex
$ for((i=0; i<${#a[@]}; i++)); do for((j=0; j<${#a[i]}; j+=2)); do
printf "\x${a[i]:j:2}"
done; done
AAAZZZ
Note that, if you have it installed, xxd
has a revert mode that you could maybe use. But we would need more information about your input format. Example:
$ echo '0x4141415A5A5A' | xxd -rp
AAAZZZ
printf "obase=2; ibase=16; %s\n" "$hexstr" | bc
?? – David C. Rankin Commented 10 hours agobc
is installed, but it is quite common as the tool to provide floating-point calculations to Linux shells. – David C. Rankin Commented 10 hours ago[0-9a-fA-F]
produces one output byte (e.g.F0
=> byte 240), not 8 characters in[01]
(F0
=>11110000
). I may be wrong. – Renaud Pacalet Commented 6 hours ago