【问题标题】:How to write binary data in Bash如何在 Bash 中写入二进制数据
【发布时间】:2021-10-21 23:25:44
【问题描述】:

假设 Bash 脚本中有一个值为“001”的变量。如何将此二进制数据作为位写入文件(作为“001”而不是“1”)

echo 将其写入为字符串,但我想写入位。

【问题讨论】:

  • 您不能将单个位写入文件。您可以写入的最小量是 8 位,即一个字节。
  • 如何将 8 位字符串变量“00000011”写入文件
  • @JeevansaiJinne printf '%s' $'\x03' > file
  • @123 这有效,但前提是值不是\x00,因为该值不能表示为参数。 printf '\x00' 有效,因为它避免了按字面传递二进制数据

标签: bash shell


【解决方案1】:

您可以使用以下命令以十六进制或八进制写入任意字节:

printf '\x03' > file   # Hex
printf '\003' > file   # Octal

如果你有二进制,那就有点诡计了,但你可以把它变成八进制:

printf '%o\n' "$((2#00000011))"

上面当然可以嵌套哪个:

binary=00000011
printf "\\$(printf '%o' "$((2#$binary))")" > file

请注意,这只适用于最多 8 位。如果你想写更长的值,你必须把它分成 8 个一组。

【讨论】:

  • 用十进制和八进制写有什么区别,都是写字节
  • 结果是一样的,不同的只是你如何指定要写入的字节。如果你想写所有的,那就是\xFF vs \377。您可以使用任何您喜欢使用的方法。
【解决方案2】:

只需在 printf 中使用%b

printf "%b" "\012"
printf "%b" "\x0a"

%b - 在解释反斜杠时打印相关参数 逃到那里

所以,上面都打印了十进制 10 的二进制值。

printf "%b" "\x0a" | od -bc

输出

0000000   012                                                            
          \n      

你甚至可以混合

printf "%b" "\12\xa\n" | od -bc

0000000   012 012 012                                                    
          \n  \n  \n            

【讨论】:

    【解决方案3】:

    您通常想要编写一个模式(例如 32 位模式)。

    # Write 32 bits 5 times to a file 
    for i in {1..5}
    do
       printf '\x12\x34\xAC\xCD' >> binaryfile.bin
    done
    

    另一个例子:

    for i in {1..255}
    do
        hx=$( printf "%x" $i )
        output="\x$hx\x00\x00\x00"
        printf "%b" $output >> binaryfile.bin 
    done
    

    【讨论】:

      【解决方案4】:

      将整数输出到文件的几个更通用的函数:

      le16 () { # little endian 16 bit;  1st param: integer to 2nd param: file 
        v=`awk -v n=$1 'BEGIN{printf "%04X", n;}'`
        echo -n -e "\\x${v:2:2}\\x${v:0:2}" >> $2
      }
      
      le32 () { # 32 bit version
        v=`awk -v n=$1 'BEGIN{printf "%08X", n;}'`
        echo -n -e "\\x${v:6:2}\\x${v:4:2}\\x${v:2:2}\\x${v:0:2}" >> $2
      }
      

      【讨论】:

        【解决方案5】:

        我最近需要这个,有人可能会觉得它有用:

        #!/bin/bash
        
        # generate bitmasks for a C array
        
        # loop counter
        NUMBER=0
        MAX_BITMASK_LENGTH=8
        # max loop value : 2^8 = 255
        MAXVAL=$((2**MAX_BITMASK_LENGTH))
        # line number
        LINE=0
        
        # echo start of C array
        echo "    const long int bitmasks[${MAX_BITMASK_LENGTH}] = {"
        
        # loop over range of values
        while [ ${NUMBER} -le ${MAXVAL} ] ; do
        
            # use bc to convert to binary
            BINARY=`echo -e "obase=2\n${NUMBER}"| bc`
        
            # print current number, linenumber, binary
            printf "%12s, /* (%i) %8s */\n" ${NUMBER} ${LINE} ${BINARY}
        
            # increase loop value to next value
            NUMBER=$(((NUMBER*2)+1))
        
            # increment line number
            LINE=$((LINE+1))
        done
        
        # echo end of C array
        echo "        };"
        

        这个输出:

        $ ./generate_bitmasks.sh
            const long int bitmasks[8] = {
                   0, /* (0)        0 */
                   1, /* (1)        1 */
                   3, /* (2)       11 */
                   7, /* (3)      111 */
                  15, /* (4)     1111 */
                  31, /* (5)    11111 */
                  63, /* (6)   111111 */
                 127, /* (7)  1111111 */
                 255, /* (8) 11111111 */
                };
        

        【讨论】:

          【解决方案6】:

          使用 bc(在 CentOS 7.4 中):

          VALUE="3F"
          INPUT_BASE=16
          OUTPUT_BASE=2
          printf "%b\n" $(bc <<< "ibase=$INPUT_BASE; obase=$OUTPUT_BASE; $VALUE")
          

          结果:111111

          如果需要前导零,则:

          VALUE="3F"
          INPUT_BASE=16
          OUTPUT_BASE=2
          printf "%16b\n" $(bc <<< "ibase=$INPUT_BASE; obase=$OUTPUT_BASE; $VALUE") | sed 's^ ^0^g'
          

          结果:0000000000111111

          注意 printf 格式中 16 的使用;更改值以限制前导零计数

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2014-10-05
            • 1970-01-01
            • 1970-01-01
            • 2018-09-04
            • 1970-01-01
            • 2017-06-03
            相关资源
            最近更新 更多