12

我想反转以下bash命令执行的操作:

$ echo $((62#a39qrT))
9207903953

即将十进制 9207903953转换为基数 62,保持bash标准为{0..9},{a..z},{A..Z}.

我知道我可以通过使用来做到这一点bc,但我必须手动转换每个字符。例如,我目前这样做:

BASE62=($(echo {0..9} {a..z} {A..Z}))
for i in $(echo "obase=62; 9207903953" | bc)
do
    echo -n ${BASE62[$i]} #Doesn't work if bc's output contains leading zeroes
done

必须有一种方法可以以一种不那么“黑客”的方式来做到这一点。你知道一种更有效地做到这一点的方法吗?

编辑:更改bc输入。

4

4 回答 4

12

我非常感谢您提出的解决方案,而且我想没有办法直接使用 bash 解决它。这是你错过的一点:

BASE62=($(echo {0..9} {a..z} {A..Z}))
for i in $(bc <<< "obase=62; 9207903953"); do
    echo -n ${BASE62[$(( 10#$i ))]}
done && echo

输出:

a39qrT
于 2013-01-23T04:14:59.223 回答
4
function base62encode() {
  bc<<<"obase=62;$1" | awk '{for (i=1; i<=NF; i++) printf "%c", $i+(($i<10)?48:(($i<36)?87:29))}'
}
  • bc<<<"obase=62;$1"转换为从 00 到 61 的以空格为前缀的十进制数字序列
  • 然后将每个数字偏移到 ASCII 表中并使用 awk 的 printf 转换为字符

或者没有 for 循环:

function base62encode() {
  bc<<<"obase=62;$1" | awk 'BEGIN{RS=" +"}/./{printf "%c", $1+(($1<10)?48:(($1<36)?87:29))}';
}
于 2016-09-17T17:38:34.810 回答
2

或者没有 bc 并且具有任意基数:

function baseXencode() {
  awk 'BEGIN{b=split(ARGV[1],D,"");n=ARGV[2];do{d=int(n/b);i=D[n-b*d+1];r=i r;n=d}while(n!=0);print r}' "$1" "$2"
}
function base62encode() {
  baseXencode 0123465789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ "$1"
}
于 2016-09-30T15:55:03.473 回答
1

gforth使用, 和tr, (tr需要使用任意 base10 到 baseX 转换函数gforth,因为bash使用不同的字符来打印基数):

n2b() { gforth -e "$1 $2 base ! . cr bye" | tr '[0-9A-z]' '[0-9a-zA-Z]' ; }
n2b 9207903953 62
n2b 9207903953 61   # Also works with other bases.
n2b 9207903953 3

输出:

a39qrT 
aT1PM8
212202201021222121202
于 2017-05-12T20:24:08.123 回答