sistema_progs

Programas para customizar o meu entorno de traballo nos meus equipos persoais
Log | Files | Refs

array-is-array.sh (5409B)


      1 #!/usr/bin/env bash
      2 
      3 if [[ ! ${BLE_VERSION-} ]]; then
      4   source ../../src/benchmark.sh
      5   _ble_bash=$((BASH_VERSINFO[0]*10000+BASH_VERSINFO[1]*100+BASH_VERSINFO[2]))
      6 fi
      7 
      8 arr1[0]=1234
      9 
     10 #------------------------------------------------------------------------------
     11 # 1 declare +a を用いる方法
     12 
     13 # broken この実装は呼び出し元のローカル変数が見えない。
     14 #   また現在の関数のローカル変数も見えない。
     15 #   更に、bash-4.2 以降でないと動かない。
     16 function ble/is-array1 { ! declare -g +a "$1" &>/dev/null; }
     17 
     18 ble-measure 'ble/is-array1 arr1' #  55.20 usec/eval
     19 ble-measure 'ble/is-array1 arr2' #  51.80 usec/eval
     20 ble-measure 'ble/is-array1 arr'  #  51.00 usec/eval
     21 
     22 #------------------------------------------------------------------------------
     23 # 2 compgen -A arrayvar を用いる方法 (不完全)
     24 
     25 # broken 指定した名前で "始まる" 配列があれば真と判定されてしまう。
     26 function ble/is-array2 { compgen -A arrayvar "$1" &>/dev/null; }
     27 
     28 ble-measure 'ble/is-array2 arr1' # 1439.90 usec/eval
     29 ble-measure 'ble/is-array2 arr2' # 1429.90 usec/eval
     30 ble-measure 'ble/is-array2 arr'  # 1439.90 usec/eval
     31 
     32 #------------------------------------------------------------------------------
     33 # 3 compgen -A arrayvar を用いる方法 (完全)
     34 
     35 function ble/is-array3 {
     36   compgen -A arrayvar "$1" >| "$_ble_util_assign_base" 2>/dev/null || return 1
     37   local REPLY; read -r < "$_ble_util_assign_base"
     38   [[ $REPLY == "$1" ]]
     39 }
     40 
     41 ble-measure 'ble/is-array3 arr1' # 1519.90 usec/eval
     42 ble-measure 'ble/is-array3 arr2' # 1469.90 usec/eval
     43 ble-measure 'ble/is-array3 arr'  # 1549.90 usec/eval
     44 
     45 # 結論として compgen を使うのが一番のボトルネックになっているので、
     46 # 一時ファイルに書き出してそれを読み出してチェックするというのは速度的な問題にはならない。
     47 # それでも 1.5ms もかかっていることには注意する。例えば 600 の配列を確認すると 1 秒になる。
     48 
     49 #------------------------------------------------------------------------------
     50 # 4 compgen -A arrayvar -X ! を用いる方法 (完全)
     51 
     52 function ble/is-array4 { compgen -A arrayvar -X \!"$1" "$1" 2>/dev/null; }
     53 
     54 ble-measure 'ble/is-array4 arr1' # 1439.90 usec/eval
     55 ble-measure 'ble/is-array4 arr2' # 1439.90 usec/eval
     56 ble-measure 'ble/is-array4 arr'  # 1439.90 usec/eval
     57 
     58 # 実は出力を確認しなくても良い。こちらの方が速い。
     59 
     60 #------------------------------------------------------------------------------
     61 # 4 bash-4.4 ${parameter@a} を用いる方法
     62 
     63 # 2018-07-15 bash-bug メーリングリストで ${param@a} の存在を知った。
     64 # bash-4.4 以降の機能の様だ。これを使えば簡単に配列属性を確認できる。
     65 
     66 if ((_ble_bash>=40400)); then
     67   function ble/is-array5 { [[ ${!1@a} == *a* ]]; }
     68   ble/is-array5 arr1 || echo 'error: 5 arr1'
     69   ble/is-array5 arr2 && echo 'error: 5 arr2'
     70   ble/is-array5 arr  && echo 'error: 5 arr'
     71 
     72   ble-measure 'ble/is-array5 arr1' # 24.80 usec/eval
     73   ble-measure 'ble/is-array5 arr2' # 23.30 usec/eval
     74   ble-measure 'ble/is-array5 arr'  # 23.10 usec/eval
     75 fi
     76 
     77 #------------------------------------------------------------------------------
     78 # 5 declare -p の結果を参照する?
     79 
     80 arr3=({1..1000})
     81 function ble/is-array6 {
     82   local __name=$1 __def
     83   ble/util/assign __def 'declare -p "$name" 2>/dev/null'
     84   local rex='^declare -[b-zA-Z]*a'
     85   [[ $__def =~ $rex ]]
     86 }
     87 ble-measure 'ble/is-array6 arr1' # 24.80 usec/eval
     88 ble-measure 'ble/is-array6 arr2' # 23.30 usec/eval
     89 ble-measure 'ble/is-array6 arr3' # 23.10 usec/eval
     90 
     91 # 2020-04-12 の計測結果 @ chatoyancy bash-5.0
     92 #   この結果を見ると実は declare -p をしてしまった方が
     93 #   compgen に頼るよりも高速な様である。
     94 #   Cygwin では余り違いが見られないが、Cygwin ならば
     95 #   恐らく bash-4.4 以降に保たれているので
     96 #   ${var@a} を使う事ができるのでそれほど気にしなくても良い?
     97 #
     98 #   481.398 usec/eval: ble/is-array4 arr1 (x500)
     99 #   479.936 usec/eval: ble/is-array4 arr2 (x500)
    100 #   479.532 usec/eval: ble/is-array4 arr (x500)
    101 #     4.422 usec/eval: ble/is-array5 arr1 (x20000)
    102 #     4.038 usec/eval: ble/is-array5 arr2 (x20000)
    103 #     4.023 usec/eval: ble/is-array5 arr (x20000)
    104 #   164.238 usec/eval: ble/is-array6 arr1 (x1000)
    105 #   165.432 usec/eval: ble/is-array6 arr2 (x1000)
    106 #   165.417 usec/eval: ble/is-array6 arr3 (x1000)
    107 #
    108 # chatoyancy bash-4.3
    109 #   389.800 usec/eval: ble/is-array4 arr1 (x500)
    110 #   387.800 usec/eval: ble/is-array4 arr2 (x500)
    111 #   389.800 usec/eval: ble/is-array4 arr (x500)
    112 #   203.800 usec/eval: ble/is-array6 arr1 (x500)
    113 #   201.800 usec/eval: ble/is-array6 arr2 (x500)
    114 #   201.800 usec/eval: ble/is-array6 arr3 (x500)
    115 #
    116 # chatoyancy bash-3.2
    117 #   401.200 usec/eval: ble/is-array4 arr1 (x500)
    118 #   401.200 usec/eval: ble/is-array4 arr2 (x500)
    119 #   401.200 usec/eval: ble/is-array4 arr (x500)
    120 #   213.200 usec/eval: ble/is-array6 arr1 (x500)
    121 #   211.200 usec/eval: ble/is-array6 arr2 (x500)
    122 #   211.200 usec/eval: ble/is-array6 arr3 (x500)
    123 #
    124 # letsnote2019 bash-4.4
    125 #   1478.000 usec/eval: ble/is-array4 arr1 (x100)
    126 #   1408.000 usec/eval: ble/is-array4 arr2 (x100)
    127 #   1518.000 usec/eval: ble/is-array4 arr (x100)
    128 #   1448.000 usec/eval: ble/is-array6 arr1 (x100)
    129 #   1468.000 usec/eval: ble/is-array6 arr2 (x100)
    130 #   1478.000 usec/eval: ble/is-array6 arr3 (x100)