在UNIX Shell脚本中将十进制转换为十六进制


110

在UNIX Shell脚本中,可以使用什么将十进制数转换为十六进制?我以为od可以解决这个问题,但是并没有意识到我正在向它提供数字的ASCII表示形式。

printf?毛!现在使用它,还有什么可用的呢?


8
我要问,printf有什么意义?许多常见的编程语言都支持类似printf的格式,因此,下面的printf解决方案无疑是开发人员最容易理解的。
Michael Scheper

4
男孩,我不知道-那是五年前!我想也许我以为那不是真正的外壳之类的东西。
skiphoppy

Answers:


108
echo "obase=16; 34" | bc

如果要过滤整个整数文件,则每行一个:

( echo "obase=16" ; cat file_of_integers ) | bc

1
我同时看了bc(1)和dc(1),却错过了那个。
Keltia

3
@skiphoppy:如果您写:echo“ obase = 16; 12 34 56” | 公元前您得到1E240,就像您写的一样:echo“ obase = 16; 123456” | 公元前。因此,在一行上处理任意整数的方法是将每个数字放在自己的行上:tr'''\ 015'<input | bc(将空白映射到换行符)。
乔纳森·莱夫勒

1
如果您碰巧拥有'bc',这很棒,但是'printf'是bash本身的一部分
FuzzyTew

1
@Bill Karwin,zsh或busybox,但也许不是我没有尝试过的一些shell?我不守纯SH安装了,但显然skiphoppy正在寻找什么其他选择有
fuzzyTew

2
@ Sridhar-Sarnobat,这十进制到十六进制。我认为您的意思是将十六进制转换为dec。为此,请设置ibase=16。您可能想阅读BC上手册以了解更多详细信息。
比尔·卡文

186

试过了printf(1)吗?

printf "%x\n" 34
22

所有外壳中都有内置函数可以完成此操作,但是移植性较差。我尚未检查POSIX sh规格是否具有这种功能。


5
POSIX的功能不比printf多。这甚至可以在“ sh”中使用。
Orwellophile

4
printf不是精确的精度。 bc是。例如,238862874857408875879219909679752457540作为输入,printf给我们“结果太大”。BC方法适用于比标准int / long / bigint大的事物
Andrew Backer 2014年

3
而且,如果您想用十六进制大写字母,请使用printf "%X"大写
X。– andrybak

3
并强制输出类似“ 0x00”的输出,可以使用printf“ 0x%02X”
gbetous

1
... bc并非在所有地方都可用(至少不是在我的嵌入式Linux上)。
Matthieu

69

十六进制到十进制:

$ echo $((0xfee10000))
4276158464

十进制到十六进制:

$ printf '%x\n' 26
1a

15
bash-4.2$ printf '%x\n' 4294967295
ffffffff

bash-4.2$ printf -v hex '%x' 4294967295
bash-4.2$ echo $hex
ffffffff

1
-v VAR是bash扩展。手册页中未提及,仅在一个printf不带参数的电话中显示
Adrian W

5

对不起,请尝试这个...

#!/bin/bash
:

declare -r HEX_DIGITS="0123456789ABCDEF"

dec_value=$1
hex_value=""

until [ $dec_value == 0 ]; do

    rem_value=$((dec_value % 16))
    dec_value=$((dec_value / 16))

    hex_digit=${HEX_DIGITS:$rem_value:1}

    hex_value="${hex_digit}${hex_value}"

done

echo -e "${hex_value}"

例:

$ ./dtoh 1024
400

1
谢谢,这对环境很有帮助。where printfhex命令不可用。
benchuk

2
@benchuk在哪里printf不可用?
Matthieu



2

就我而言,我偶然发现了使用printf解决方案的一个问题:

$ printf "%x" 008 bash: printf: 008: invalid octal number

最简单的方法是将解决方案与bc一起使用,在更高版本中建议:

$ bc <<< "obase=16; 008" 8


您的解决方案对几年前撰写的内容有何帮助?
Matthieu

@Matthieu它提到了带前导零的数字问题,Bash printf无奈地将其解释为八进制,并演示了避免该问题的解决方案。
mwfearnley

2
xd() {
    printf "hex> "
    while read i
    do
        printf "dec  $(( 0x${i} ))\n\nhex> "
    done
}
dx() {
    printf "dec> "
    while read i
    do
        printf 'hex  %x\n\ndec> ' $i
    done
}

1
# number conversion.

while `test $ans='y'`
do
    echo "Menu"
    echo "1.Decimal to Hexadecimal"
    echo "2.Decimal to Octal"
    echo "3.Hexadecimal to Binary"
    echo "4.Octal to Binary"
    echo "5.Hexadecimal to  Octal"
    echo "6.Octal to Hexadecimal"
    echo "7.Exit"

    read choice
    case $choice in

        1) echo "Enter the decimal no."
           read n
           hex=`echo "ibase=10;obase=16;$n"|bc`
           echo "The hexadecimal no. is $hex"
           ;;

        2) echo "Enter the decimal no."
           read n
           oct=`echo "ibase=10;obase=8;$n"|bc`
           echo "The octal no. is $oct"
           ;;

        3) echo "Enter the hexadecimal no."
           read n
           binary=`echo "ibase=16;obase=2;$n"|bc`
           echo "The binary no. is $binary"
           ;;

        4) echo "Enter the octal no."
           read n
           binary=`echo "ibase=8;obase=2;$n"|bc`
           echo "The binary no. is $binary"
           ;;

        5) echo "Enter the hexadecimal no."
           read n
           oct=`echo "ibase=16;obase=8;$n"|bc`
           echo "The octal no. is $oct"
           ;;

        6) echo "Enter the octal no."
           read n
           hex=`echo "ibase=8;obase=16;$n"|bc`
           echo "The hexadecimal no. is $hex"
           ;;

        7) exit 
        ;;
        *) echo "invalid no." 
        ;;

    esac
done

1

这不是shell脚本,而是我用来在bin / oct / dec / hex之间转换数字的cli工具:

    #!/usr/bin/perl

    if (@ARGV < 2) {
      printf("Convert numbers among bin/oct/dec/hex\n");
      printf("\nUsage: base b/o/d/x num num2 ... \n");
      exit;
    }

    for ($i=1; $i<@ARGV; $i++) {
      if ($ARGV[0] eq "b") {
                    $num = oct("0b$ARGV[$i]");
      } elsif ($ARGV[0] eq "o") {
                    $num = oct($ARGV[$i]);
      } elsif ($ARGV[0] eq "d") {
                    $num = $ARGV[$i];
      } elsif ($ARGV[0] eq "h") {
                    $num = hex($ARGV[$i]);
      } else {
                    printf("Usage: base b/o/d/x num num2 ... \n");
                    exit;
      }
      printf("0x%x = 0d%d = 0%o = 0b%b\n", $num, $num, $num, $num);
    }
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.