在bash

时间:2017-04-09 10:57:49

标签: bash shell math scripting arithmetic-expressions

我一直在使用非常基本的,大部分直接的方法将基数为10的数字{1..256}转换为基数为4或四进制数。我一直在使用简单的除法$(($NUM/4))得到主要结果,以便得到余数$(($NUM%4)),然后反向打印余数以得到结果。我使用以下bash脚本来执行此操作:

#!/bin/bash

NUM="$1"

main() {

local EXP1=$(($NUM/4))
local REM1=$(($NUM%4))
local EXP2=$(($EXP1/4))
local REM2=$(($EXP1%4))
local EXP3=$(($EXP2/4))
local REM3=$(($EXP2%4))
local EXP4=$(($EXP3/4))
local REM4=$(($EXP3%4))

echo "
$EXP1 remainder $REM1
$EXP2 remainder $REM2
$EXP3 remainder $REM3
$EXP4 remainder $REM4

Answer: $REM4$REM3$REM2$REM1
"
}

main

此脚本适用于数字0-255或1-256。但是超出这个(这些)范围,结果变得混杂并经常重复或不准确。这不是一个很大的问题,因为我不打算将数字转换为256或小于0(负数[尚])。

我的问题是:"是否有更简化的方法可以使用exprbc

2 个答案:

答案 0 :(得分:2)

使用brace expansion

创建一个查找表
$ echo {a..c}
a b c    
$ echo {a..c}{r..s}
ar as br bs cr cs
$ echo {0..3}{0..3}
00 01 02 03 10 11 12 13 20 21 22 23 30 31 32 33

等等,对于0-255十进制到base-4

$ base4=({0..3}{0..3}{0..3}{0..3})
$ echo "${base4[34]}"
0202
$ echo "${base4[255]}"
3333

答案 1 :(得分:2)

中的Base 4转换
int2b4() {
    local val out num ret=\\n;
    for ((val=$1;val;val/=4)){
        out=$((val%4))$out;
    }
    printf ${2+-v} $2 %s${ret[${2+1}]} $out
}

仅使用1个参数调用,这将转换为 base 4 并打印结果,后跟换行符。如果存在第二个参数,则将填充此名称的变量,不打印。

int2b4 135
2013
int2b4 12345678
233012011032

int2b4 5432 var
echo $var
1110320

详细说明:

  • 主要部分是(可写):

    out=""
    for (( val=$1 ; val > 0 ; val = val / 4 )) ;do
        out="$((val%4))$out"
        done
    

    我们很容易理解转换循环(我希望)

  • local确保out val num为本地空变量并在本地初始化ret='\n'

  • printf行使用一些bashisms

      如果${2+-v}为空,则
    • $2为空,如果不为则代表-v
    • ${ret[${2+1}]}分别成为${ret[]}(或${ret[0]})和${ret[1]}

    所以这一行成了

    printf "%s\n" $out
    

    如果没有第二个参数($ 2)和

     printf -v var "%s" $out
    

    如果第二个参数是var(请注意,没有换行符附加到填充变量,但是为终端打印添加了换行符。)

转换回小数:

有一个 bashism 让你可以用bash下的任意基数进行计算:

echo $[4#$var]
5432

echo $[4#1110320]
5432

在脚本中:

for integer in {1234..1248};do
    int2b4 $integer quaternary;
    backint=$[4#$quaternary];
    echo $integer $quaternary $backint;
  done

1234 103102 1234
1235 103103 1235
1236 103110 1236
1237 103111 1237
1238 103112 1238
1239 103113 1239
1240 103120 1240
1241 103121 1241
1242 103122 1242
1243 103123 1243
1244 103130 1244
1245 103131 1245
1246 103132 1246
1247 103133 1247
1248 103200 1248