在 Linux CLI 上将十六进制转换为二进制

在 Linux CLI 上将十六进制转换为二进制

我有一个文本文件,其中的行(每行 631 个字符)由 16 个十六进制数字组成0,1,2,...,9,A,B,...,F。我想将每个数字替换为相应的4位0和1,即0替换为0000,1替换为0001,...,F替换为1111,然后将文件另存为.bin。我如何在 Linux 终端中执行此操作?

我的文本文件的一些行是:

85868D6B0FD5F3186DE92A7FC023CC848110FE61E3045B24BD905C8FDF34698794718CB2BAFF2AFC488C07B01510646141290A8FE55BF41F9D5033B13B31473FB4F7E199624370DC9C7587E5FB84B209B104B2BC194243EFC77C479BEA6778C73FB55939CB8654B1EB0B597CEA9507FE5A9636229BE0E7ECA27844D3A4AE16096D9DDC125728A1BF0C3623518311CF7CE629C15EA767E1F6C992106E86D962D47E307AE9F71FE5C6B664820E3D7521D0F783913E8A116BFD42C65FD2E28C9114CF4BFCB8A2AFD9979E7B5EBC7B59C7A31A7C12931D2C794EF5AED991B32560BBEFCC82D3A6AC6D371C7AC6C06DED6BCEFFC3D9E11A17B4738EA2ECF8CDD14805E57C50F973C6832DB94517A71C06E18329694B8CB7F7028730E54F74E27EF35B3D776A7E46A3F187691D460CBFBCD14BAC4AED32E5592AFDAEC5206
6321EB4F15D5F01D2A5F7474AC6FFCD1A8B52E680AC52CA9B500C956FD269DB8107EFCF6EC0B23B2C54B3A727CC53F6793019BF0D95A037485413576E4A0172A597027ED71D6E785430FA4748E164E5290214B01740736C0EC79D286692170B6EFBA21592EC485350F0DC6C635CD3FA7DAED258405C4247BFA68613B5F7CBEC903E16EA2E780D0934F0A2918F837CF0115B3D76AAFD3F37D905F9572D334D959DDD22C37EBA7707A76333A491F79B9C53A7912AEA38ED400949EB9AD9FCEE71765F4F4A2E21C481A509AB6807DDF5374D9A1A4D0C589E628CAA3C6DC9E4A5C1A7EF3C36A4D2231E2C1E856A19B6F7F4DE713D5BE8A4EFA750FB29A34F00754D875C22C2FC981FAECCC7113D1B0D6FF3BCC747852789A662D104DF1A8C90EB4DDFA48502A3BA9AAE70E7229E8A3D6FBBD00C19D99765BAFC9B09D547
2F75AC10A9E20C07DD4686C5706F66EB1AB33ED9DEDAD69079B6EC0C24C8DF24CB1855825D80CD484E5623BB246041D29240720500EA87586CC4CE5A00990EF8B5B7E2A3CF3E997323870499451E7BFA7F23A2208523B84A98DDC0763701C1AB292D854ADA8FB2E060088D7B3436571745DF25182D7F5A646A6F7DD830B9CCC12C37D416882DD7AAA0E8CB2CE50CE33AD1674C0E78E0F171DEC2D087C6CF2E711FAC2548CCB8C0312D59055A0A3A145B402A749F768F637549E0749215B5542BBC9D07EF9416C1BAB1FBEAC4709C458E7C266342908421BC8F67B7E21ED228D13A0F2750C290EFF8CAF7D2AD6D6C2CB12B81570190E1BC555E0CFBA4951BEAD3740D3BEBF2C7BF2AB64C7F046E5B865D85A1411F854906C05785A0A3684EC0F69D9BAB047A9EC17F973E78A92838C73270F97E54CEF4FABAA82876F

答案1

xxd -r -p

例子:

sudo apt install xxd
printf 123456789ABCDEF0 | xxd -r -p | od -A n -t x1 -v

给出:

 12 34 56 78 9a bc de f0

od将原始字节显示为人类可读字节,这意味着它xxd -r -p做了我们想要的并将人类可读字节转换123456789ABCDEF0为相应的原始字节。

在 Ubuntu 19.04、xxd V1.10 上测试。

答案2

将我的评论发布为答案,标记为“已解决”

for n in $(cat myfile | tr 'a-f' 'A-F');do echo "obase=2; ibase=16; $n" | bc ;done

好吧,根据你所说的以及我的理解,我给你一些建议。第一个将每个十六进制行转换为新的二进制行,并在每行末尾放置一个换行符。这是该解决方案:

cat myfile | while read line
do
  len=${#line}
  binline=""
  index=1
  while [ ${index} -le ${len} ]
  do
    hex=$(echo ${line} | cut -c ${index} | tr 'a-f' 'A-F')
    bin=$(echo "obase=2; ibase=16; ${hex}"|bc)
    padbin=$(printf "%04d" ${bin})
    binline="${binline}${padbin}"
    (( index++ ))
  done
  echo ${binline} >> program.bin
done

而且,如果我没有记错的话,您正在尝试使用这个二进制文件作为嵌入式系统或类似系统的程序。如果是这种情况,换行符可能会出现问题。如果是这种情况,即您希望整个文件作为一个巨大的行,您可以使用以下代码片段:

cat myfile | while read line
do
  len=${#line}
  index=1
  while [ ${index} -le ${len} ]
  do
     hex=$(echo ${line} | cut -c ${index} | tr 'a-f' 'A-F')
     bin=$(echo "obase=2; ibase=16; ${hex}"|bc)
     printf "%04d" ${bin} >> p2.bin
     (( index++ ))
  done
done

话虽如此,如果您的十六进制值文件大小为千兆字节甚至几百兆字节,bash 会抱怨并可能抛出一个神秘的错误。因此,最好将此输入文件切成更易于管理的块并逐个处理它们。

请注意,我以最简单的方式编写了这些脚本以便于理解。因此,当您运行它们时,它会产生一些性能损失。 3行大约需要6秒的处理时间。如果您发现等待无法忍受,则由您来优化它。

答案3

假设您希望将十六进制字符串转换为二进制字符串(每个 2 个十六进制数字字符由 8 个字符组成的序列01,而不是将它们转换为二进制字符串,我会使用perl

$ echo 00ffaa | perl -lne 'print unpack "B*", pack"H*", $_'
000000001111111110101010

xxd

$ echo 00ffaa | xxd -p -r | xxd -b -g 0 -c 8 | cut -c11-74
000000001111111110101010

答案4

您可以使用 printf:

$ printf '%04d\n' 0
0000

$ printf '%04d\n' 1
0001

或者 POSIX Awk标准库:

$ awklib 'BEGIN {print base_conv("F", 16, 2)}'
1111

相关内容