[20191011]bash任意进制编码表.txt

--//bash可以使用任意进制编码转化为十进制.我想了解内部编码:
--//实际上受字符集的限制,"任意"进制有限制的.测试看看最大是多少.

1.input base最大支持多少.

$  echo $((16#F))
15

$  echo $((16#f))
15

--//说明:前面16表示16进制,F表示编码,结果输出10进制 15.
--//注意看大小写输出都是15.说明16进制编码 0-9,a-f  或者0-9,A-F.

$  echo $((64#F))
41

$  echo $((65#F))
-bash: 65#F: invalid arithmetic base (error token is "65#F")

--//65进制不支持.从这里看出ibase最大是64.看看64进制编码情况如何?

2.看看64进制编码:

$  echo $((64#1))
1

$  echo $((64#a))
10

$  echo $((64#A))
36

--//可以大概猜测bash 64进制编码从0开始. 0-9 , a-z , A-Z.这样仅仅62个编码.还剩下2个.
--//经常反复测试,你也可以写脚本测试.

$  echo $((64#@))
62

$  echo $((64#_))
63

--//这样完整的编码如下:
$ base64=$(echo {0..9} {a..z} {A..Z} @ _)
$ echo $base64
0 1 2 3 4 5 6 7 8 9 a b c d e f g h i j k l m n o p q r s t u v w x y z A B C D E F G H I J K L M N O P Q R S T U V W X Y Z @ _

--//定义成bash数组如下:
$ BASE64=($(echo {0..9} {a..z} {A..Z} @ _))
$ echo ${BASE64[*]}
0 1 2 3 4 5 6 7 8 9 a b c d e f g h i j k l m n o p q r s t u v w x y z A B C D E F G H I J K L M N O P Q R S T U V W X Y Z @ _

--//其它进制仅仅编码缩短,估计在36进制以内大小写可以混用.测试如下:
$ echo $((36#A))
10

$ echo $((36#a))
10

$ echo $((36#aA))
370
--//大小写混合没问题.在36进制以内.

$ echo $((37#a))
10

$ echo $((37#A))
36

--//36进制下大小写输入一致.而37进制就不是这样的情况了.

3.为什么要了解这些?
--//有了bash 64进制码表,我就可以使用bash转换oracle rowid的相关信息,虽然oracle rowid也是64进制编码,但是编码排列不一样.
--//而通过bash很容易转化成对应的10进制:
--//比如:
SCOTT@test01p> select rowid ,t1.* from t1 where id in (63,64);
ROWID                      ID T1NAME
------------------ ---------- ----------------------
AAAG2DAALAAAADDAA+         63 t10000000063
AAAG2DAALAAAADDAA/         64 t10000000064

SCOTT@test01p> @ rowid AAAG2DAALAAAADDAA+
    OBJECT       FILE      BLOCK        ROW ROWID_DBA            DBA                  TEXT
---------- ---------- ---------- ---------- -------------------- -------------------- ----------------------------------------
     28035         11        195         62  0x2C000C3           11,195               alter system dump datafile 11 block 195

--//rowid前6位是data_object_id. AAAG2D.
--//Rowid采用64位进制编码,编码如下:
A-Z <==> 0 - 25  (26)
a-z <==> 26 - 51 (26)
0-9 <==> 52 - 61 (10)
+/  <==> 62 - 63 (2)

--//码表就是 echo {A..Z} {a..z} {0..9} +/ | tr -d " "

$ echo AAAG2D | tr $( echo {A..Z} {a..z} {0..9} +/ | tr -d " ")  $( echo {0..9} {a..z} {A..Z} @ _| tr -d " ")
0006S3

$ echo $((64#0006S3))
28035
--//完成能对上.再来看看block号=AAAADD.

$ echo $(( 64#$( echo AAAADD | tr $( echo {A..Z} {a..z} {0..9} +/ | tr -d " ")  $( echo {0..9} {a..z} {A..Z} @ _| tr -d " ")) ))
195

$ echo $(( 64#$( echo AA+ | tr $( echo {A..Z} {a..z} {0..9} +/ | tr -d " ")  $( echo {0..9} {a..z} {A..Z} @ _| tr -d " ")) ))
62

$ echo $(( 64#$( echo AA/ | tr $( echo {A..Z} {a..z} {0..9} +/ | tr -d " ")  $( echo {0..9} {a..z} {A..Z} @ _| tr -d " ")) ))
63

--//也能对上.还可以使用这个将sql_id 推导出 hash_value.比如:
--//链接:http://blog.itpub.net/267265/viewspace-2142512/
select * from emp where deptno=10;
--//查询可以知道sql_id='557p4j1ggw222'.

SCOTT@book> select sql_text c70,sql_id,hash_value  from v$sql where sql_id = '557p4j1ggw222';
C70                                SQL_ID        HASH_VALUE
---------------------------------- ------------- ----------
select * from emp where deptno=10  557p4j1ggw222 1593706562

SCOTT@book> select name c70,hash_value,full_hash_value from V$DB_OBJECT_CACHE where name like '%emp%' and hash_value=1593706562;
C70                               HASH_VALUE FULL_HASH_VALUE
--------------------------------- ---------- --------------------------------
select * from emp where deptno=10 1593706562 8bb974871a4f8c88529ea4885efe0842
select * from emp where deptno=10 1593706562 8bb974871a4f8c88529ea4885efe0842

--//sql_id=557p4j1ggw222,sql_id采用32进制,编码是0-9,a-z .没有eilo这4个字符,正好32个.我以前提过去掉eilo主要目的是这些看起来像数字0,1.

$ echo $(( 32#$( echo 557p4j1ggw222  | tr $( echo {0..9} {a..z} | tr -d "eilo ")  $( echo {0..9} {a..v} | tr -d " ")) ))
5953376663046588482

$ echo "obase=16;5953376663046588482" | bc -lq
529EA4885EFE0842

$ echo "obase=10;ibase=16;5EFE0842" | bc -lq
1593706562

--//输出10进制 5953376663046588482 转化16进制是 0x529ea4885efe0842,后8位0x5e5efe0842(16进制)就是hash_value.
--//0x5efe0842 = 1593706562
--//正好与输出的HASH_VALUE能对上.

4.附上rowid脚本如下:
$ cat rowid.sql
set verify off
column dba format a20
column text format a40
SELECT DBMS_ROWID.ROWID_OBJECT ('&1') "OBJECT",
       DBMS_ROWID.ROWID_RELATIVE_FNO ('&1') "FILE",
       DBMS_ROWID.ROWID_BLOCK_NUMBER ('&1') "BLOCK",
       DBMS_ROWID.ROWID_ROW_NUMBER ('&1') "ROW",
       lpad('0x'||trim(to_char(dbms_utility.MAKE_DATA_BLOCK_ADDRESS(dbms_rowid.ROWID_RELATIVE_FNO('&1'),dbms_rowid.ROWID_BLOCK_NUMBER('&1')), 'XXXXXXXX')), 10) rowid_dba,
          DBMS_ROWID.ROWID_RELATIVE_FNO ('&1')
       || ','
       || DBMS_ROWID.ROWID_BLOCK_NUMBER ('&1')
          "DBA",
          'alter system dump datafile '
       || DBMS_ROWID.ROWID_RELATIVE_FNO ('&1')
       || ' block '
       || DBMS_ROWID.ROWID_BLOCK_NUMBER ('&1')
       || ' ;'
          text
  FROM DUAL;

内容来源于网络如有侵权请私信删除
你还没有登录,请先登录注册
  • 还没有人评论,欢迎说说您的想法!