Код отслеживания Google Analytics.

Feb 12, 2010

bash associative arrays(map, hash or how you them calls). part II

This is second part of story about associative arrays in bash. You will find first one here.

Well after very serious criticism about variable approach we have to look at second way. It is very simple - two arrays - keys and values.



the callpart of code
getMapValue "${mapName}" "${someKey}"
...
local mapName="$1"
local index=$(getIndex $(getKeyArrayName "${mapName}") "$2")
local valueArrayName=$(getValueArrayName "${mapName}")
eval local valueArrayLength="\${#${valueArrayName}[@]}"
if [[ -z "${index}" || "${valueArrayLength}" -le "${index}" ]]; then
    return 1 #there is no value for the key "$2" in map "mapName"
fi
eval local currentValue="\${${valueArrayName}[${index}]}"
printf "%s\n" "${currentValue}"
putMapValue "${mapName}" "${someKey}" "${someValue}"
...
local mapName="$1"
local key="$2"
local currentValue=$(printf "%s\n" "$3" | sed 's|"|\\"|g')
local keyArrayName=$(getKeyArrayName "${mapName}")
local index=$(getIndex "${keyArrayName}" "${key}")
local valueArrayName=$(getValueArrayName "${mapName}")
eval local valueArrayLength="\${#${valueArrayName}[@]}"
if [[ -z "${index}" || "${valueArrayLength}" -le "${index}" ]]; then
    eval "${keyArrayName}+=( '${key}' )"
    eval "${valueArrayName}+=( '${currentValue}' )"
else
    eval "${valueArrayName}[${index}]=\"${currentValue}\""
fi
getMapKeys "${mapName}"
...
local keys=""
local keyArrayName=$(getKeyArrayName "$1")
eval local length="\${#${keyArrayName}[@]}"
for (( i=0; i<${length}; i++ )); do
    eval local currentKey="\${${keyArrayName}[${i}]}"
    if [[ -n "${keys}" ]]; then
        keys+="$IFS"
    fi
    keys+="${currentKey}"
done
printf "%s\n" "${keys}"
removeMapKey "${mapName}" "${someKey}"
...
local mapName="$1"
local key="$2"
local keyArrayName=$(getKeyArrayName "${mapName}")
local valueArrayName=$(getValueArrayName "${mapName}")
local index=$(getIndex "${keyArrayName}" "$2")
eval local valueArrayLength="\${#${valueArrayName}[@]}"
if [[ -z "${index}" || "${valueArrayLength}" -le "${index}" ]]; then
    return 1 #there is no key "$2" in map "mapName"
fi
for (( ; index<${valueArrayLength}-1; index++ )); do
    eval "${keyArrayName}[${index}]=\${${keyArrayName}[((index+1))]}"
    eval "${valueArrayName}[${index}]=\${${valueArrayName}[((index+1))]}"
done
eval unset ${keyArrayName}[${index}]
eval unset ${valueArrayName}[${index}]
unsetMap "${mapName}"
...
local mapName="$1"
local keyArrayName=$(getKeyArrayName "${mapName}")
local valueArrayName=$(getValueArrayName "${mapName}")
eval unset ${keyArrayName}
eval unset ${valueArrayName}
isMap "${mapName}"
...
local testStr=$(getMapKeys "$1")
[[ -n "${testStr}" ]]
As you can see the main functions need number of support routines:
getKeyArrayName "${mapName}"
...
printf "%s%s" "$1" "${KEY_SUFFIX}"
getValueArrayName "${mapName}"
...
printf "%s%s" "$1" "${VALUE_SUFFIX}"
getIndex "${keyArrayName}" "${key}"
...
local arrayName="$1"
eval local length="\${#${arrayName}[@]}"
local i=0;
local indexForReturn=""
while [[ -z "${indexForReturn}" && ${i} -lt ${length} ]]; do
    eval local currentValue="\${${arrayName}[$i]}"
    [[ "${currentValue}" = "$2" ]] && indexForReturn="$i"
    (( i++ ))
done
[[ -n "${indexForReturn}" ]] && printf "%s\n" "${indexForReturn}"
Actually - it is all. The full code of map routines for bash is a base of my library which I call shell-framework and you can find it at http://shell-framework.origo.ethz.ch/

No comments: