title: bash, eval, protect pipes and colon in string
body: <p>Here is the simplest distilled version of my problem.  The complexity that remains is for good reasons even if not self evident here.  Additionally the script is internal and has no chance of executing malicious code, so the eval is perfectly fine; don't need to hear about how evil it is...  ;)  Assume for the moment that the pipes and colons in the key string are required delimiters.</p>
  
  <pre><code>key="target|platform|repo:revision"
  hashname="hashmap"
  declare -A $hashname
  
  eval $hashname[$key]=0
  echo $(eval $hashname[$key])
  </code></pre>
  
  <p>Of course the last two lines have problems because the eval is acting on the pipes and colons inside of the $key variable.  My question is how can I protect a string like this from the eval?  And I need the eval because I am referring to the hashmap's name rather than it itself.  Thanks in advance.</p>
  
  <p>==================================================================================</p>
  
  <p>Ok I am actually beginning to think that my problem is not with the pipes and colon and the eval.  So Let me paste the real code</p>
  
  <pre><code>function print_hashmap()
  {
      local hashname=$1
      for key in `eval echo \$\{\!$hashname[@]\}`; do
          local deref="$hashname[$key]"
          local value=${!deref}
          echo "key=${key} value=${value}"
      done
  }
  function create_permutations2()
  {
      local hashname=$1   ; shift
      local builds=$1     ; shift
      local items=$1      ; shift
      local separators=$@
  
      echo "create_permutations(hashname=${hashname}, builds=${builds}, items=${items}, separators=${separators})"
  
      if [ NULL != "${builds}" ]; then
          for build in `echo $builds | tr ',' ' '`; do
              local target="${build%%:*}"
              local platforms="${build##*:}"
              for platform in `echo $platforms | tr '|' ' '`; do
                  local key=
                  local ref=
                  if [ NULL != "${items}" ]; then
                      if [ NULL == "${separators}" ]; then separators=' '; fi
                      for separator in $separators; do
                          items=`echo $items | tr $separator ' '`
                      done
                      for item in $items; do
                          key="${target}|${platform}|${item}"
                          ref="$hashname[$key]"
                          declare "$ref"=0
                      done
                  else
                      key="${target}|${platform}"
                      ref="$hashname[$key]"
                      declare "$ref"=0
                  fi
              done
          done
      fi
  
      echo "created the following permutations:"
      print_hashmap $hashname
  }
  builds="k:r|s|w,l:r|s|w"
  repos="c:master,m:master"
  hashname="hashmap"
  declare -A $hashname
  
  create_permutations2 $hashname $builds $repos ","
  print_hashmap $hashname
  </code></pre>
  
  <p>I recently modified my code to conform with FatalError's suggestions to use ref instead of eval and the error is the same:  syntax error in expression (error token near :master)</p>