すでに、PHP,javascript,python,rubyで構築した62進数ライブラリですが、ターミナルで使いたいので、bash(shell)で書いて見ました。
これまで、62進数は、時計フォーマットの圧縮に最適ということを伝えてきましたが、大きな桁数に対しても有効なので、たくさんの桁の数値を扱う場合はまあまあの圧縮率があります。
ただし、デメリットとして、内部loopが増えると、処理速度はとても遅くなるので、ログ解析などでレコード単位で使ってしまうと眠くなるほど遅延する事があるので、要注意です。
あと、もうひとつデメリットとしては、エンコードした後の62進数文字列は、ファイル名にした場合、10進数とは昇順の並びが変わってしまうので、若い日付順などとして使いたい場合は気をつけないとバグの元になります。
ソースコード
#!/bin/bash
decimal62_char="0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
function decimal62_encode(){
num=$1
str=()
cn=${#decimal62_char}
while [ $num -ne 0 ]
do
a1=`expr $num / $cn`;
a3=`expr $a1 \* $cn`
a2=`expr $num \- $a3`
s=${decimal62_char:$a2:1}
str=($s "${str[@]}")
num=$a1
done
res="$(IFS=; echo "${str[*]}")"
echo $res
}
function decimal62_decode(){
str=$1
declare -A chrs
cn=${#decimal62_char}
max1=`expr $cn \- 1`
for i in `seq 0 $max1`
do
s=${decimal62_char:$i:1}
chrs[$s]=$i
done
num=0
max2=`expr ${#str} \- 1`
for i in `seq 0 $max2`
do
a=`expr $i \+ 1`
s=${str:`expr $a \* -1`:1}
p=$(($cn**$i))
num=`expr $num + ${chrs["$s"]} \* $p`
done
echo $num
}
enc=(`decimal62_encode 20180425231245`)
dec=(`decimal62_decode $enc`)
echo $enc
echo $dec
実行
$ bash decimal62.sh
> 5JhPVGod
> 20180425231245
コマンドとして使いたい場合は、内部の実行行をとって、encodeとdecodeを分けてbinフォルダなどに入れてお使いください。
適当に解説
shellは関数の扱いや、変数、配列の扱いが非常にやりにくいので、構文に気をつけて行いました。
変数は宣言時に"hoge=123"として、それを参照して使うときは"echo $hoge"となります。
通常プログラムをやっている人なら、違和感ありまくりでしょうね。
あと、四則演算を行う際に都度"expr"関数を使ってやらなければいけないので、この点も慣れないうちはまあまあめんどくさいでしょう。
ちなみに、今回べき乗処理を行なっていて、"$((a**b))"という書き方をしています。
このやり方はまあまあ使いやすかったのですが、四則演算との整合性は無視して記述してしまいました。
あと、shellの時に毎回書いてますが、関数の引渡し値を"$1"として受け取っているのがいまだにどうしても納得いかず、なぜ"function()"という書き方をさせておいて、$1で受け取るのか、不思議です。
プログラムの構文としては、非常に扱いづらいのはいうまでもありません。
まあ愚痴はその辺にして、慣れてしまえばこれはこれでいいとしましょう。
多言語対応
0 件のコメント:
コメントを投稿