# The sh nonassoc arrays (support integer indexes with holes) # manipulation function for dash # Assoc array emulate see as.sh example dim() - Initialize/Set/Unset variable or array elements. dim variable_name/array arguments the format a each argument: "[]" # make new array or quick (without unsets) clearing # if val_setted then produce error # set type $1 as array; array=(); idx=0 ="value" # paste value # val_setted=1; val+="value" '$var' # paste value from $var # val_setted=1; val+=$var "[idx_expr]" # set idx from expression # set type $1 as array # store(); idx=$((idx_expr)) "[#]" # set idx from current number elements # set type $1 as array # store(); idx=${#array[*]} "a[#]" # val_setted=1; val+=${#a[*]} "a[aidx_expr]" # val_setted=1; val+=${a[$((aidx_expr))]} "a[?word]" # find element with value "word" # if found val+=$a_index_found # else val+=${#a[*]]} # val_setted=1; "-" # unset array[idx] # if val_setted then error "+" # store() and new cycle, # need the next arg as a variable_name/array "-+" # unset array[*] # if val_setted then error # start new cycle, the next arg # as a new variable_name/array E # compute a expression with splitted val and first arg # See the ``Example'' section # if val_setted==0 then produce error # if type $1 = var then val=$(($val$var)) # if type $1 = array then val=$(($val(array[idx]))) "." # strip array size to the current idx elements # type $1 != array then produce error # ${#array[*]}=(idx+val_setted) "" # grow up array size, # copy [idx..#] to [idx+expr .. #+expr] # if val_setted then produce error # if type $1 as array with holes then produce error "a[*:offset.lenght]" # val_setted=1; val+="${a[*]:offset:lenght}" "a[!*:offset.lenght]" # val_setted=1; val+="${!a[*]:offset:lenght}" # for :off:len bash have not the one expression analogy :) "a[!@:offset.lenght]" # add elements from (other) keys subarray # bash code: # inc_idx=0; keys=(${!a[@]}) # for e in ${keys[*]:offset:lenght}; do # if [[ inc_idx -eq 0 ]]; then # inc_idx=1 # val_setted=1; val+=$e # else # store 1 # idx+=1 # val=$e # fi # done # for :off:len bash have not the one expression analogy :) "a[@:offset.lenght]" # add elements from (other) subarray # bash code: # inc_idx=0 # for e in "${a[@]:offset:lenght}"; do # ... the body see in "a[!@:offset.lenght]" # done 'a[$]' # make string into the varname for use as "local $varname" 'a[$:offs.l]' # it does add to the varname the list # a[$]: "a_N_=0 a_HI_= a=" # a[$:offs.l]: "a_$((offs+1))_... a_$((offs+l-1))_" # (see the "Global variables ..." section) # and after use it in "local" it does simulate bash code: # local -a a=() # next calls "dim a array_args..." using local a[], # but before index < offs+l ! But you can add with offset. # Use offs>0 for add only, usage without 'a[$]' do not produce # auto clearing. # if type $1 is array then produce error # if offs<0 then produce error # if l="" or l<0 then produce error Notes: variable_name is not array by default if any a next arg from [] [idx] [#] varname[idx | # | @... | !@...] +expr then switch type of variable_name as a array name Initially the val= is clean, variable reset while really val_setted!=0 but you can get previous a var value with next arg '$variable'. Warning: do not forgotten really put $, for a simple string use single quote! example: make message with two elements of array: msg="first element: '" dim msg '$msg' "a[0]" ="' second: '" "a[1]" ="'" echo "$msg" `offset' and `lenght' are optional, support short subarray forms: a[@] a[!@] a[@:offset] a[@:.lenght] and etc, but a[$:.lenght] only ':' equivalent to '.', "a[code.offset.lenght]" accept too identically idx_expr, offset and lenght must have simple expression for dash $((idx_expr)) If idx_expr or offset evaluates to a number less than zero, set the value is used as an offset from the end of the array (idx=${#array[*]}+idx). Result must >= 0 Function store() with arg for reset val_setted have the pseudo code: store() { if val_setted; then if type($1)==array ? array[${idx:-0}]=$val : variable_name=$val val_setted=$1; val= fi } The string list from a[*] or a[!*] have the separator as the first character of the $IFS value Global variables or generated into a list by a[$.lenght] for local: array for 0-elements array_[0-9]*_ for 1..n-elements array_N_ for the elements number array_HI_ - list indexses for a array with holes Internal functions: _dim_F_*_ This code have local variables _*_ for true $((expression)) and eval's with previous scope vars without start and end '_' in the name, but two '__' possible ok. You can usage v=a as v=${a[0]}, it more quicker vs ``dim v "a[0]"'', but do not use a=val as a[0]=val if a[0] unsets before. Use dim a '[0]' =val Example: Use ``dim'' for the level variable indirection: # test data v=4 dim a '[]' =0 '[1]' =1 '[2]' =2 v=4 ref=v dim a '[]' =0 '[1]' =1 '[2]' =2 # increment variable by reference # make mesage for show result inc_val() { dim "$1" =+1 E + msg "=$1='" "\$$1" ="'" } # add to the $1 array's $2-th element a value $3 # $1[$2]=$1[$2]+$3 # make mesage for show result inc_element() { dim "$1" "[$2]" "=+$3" E + msg "=$1[$2]='" "$1[$2]" ="'" } # demo inc_val $ref && echo "$msg" inc_element a 3 $ref+2 && echo "$msg" # outs: v='5' a[3]='7' Example: bubble sort integers a[] with holes, make out continious o[] bash: # example holes initialize declare -ia o a=(1 [5]=5 6 [9]=9) bubble_sort() { local -ia keys=(${!a[@]}) local -i i j kj j_offs # j_offs= bash internaly for i in "${a[@]}"; do for kj in ${keys[@]: ++j_offs}; do # the space before ++j_offs need! j=${a[kj]} [[ j -lt i ]] && { a[kj]=$i; i=j; } done o+=(i) done } dash + dim(): # example holes initialize dim a '[]' =1 '[5]' =5 '[#]' =6 '[9]' =9 + o '[]' bubble_sort() { # make safe integers lists string keys="key1 key2..." local IFS=' ' keys keys_j i j local ki kj j_offs= # integers dim keys "a[!*]" for ki in $keys; do dim i "a[ki]" + keys_j "a[!*:j_offs=j_offs+1]" for kj in $keys_j; do dim j "a[kj]" [ $j -lt $i ] && { dim a "[kj]" =$i; i=$j; } done dim o "[#]" =$i done } Other examples: t.sh: have code for show arrays in the bash-like form, for example a=(0 [2]=2 3 [5]='a*b') as.sh: assoc array, load words from file, show the frequence usage a each word (without sort) asq.sh: it load words with the manualy assoc-arrays realization without the `dim' function, but have qsort() used dim()