skip to Main Content

This is the same situation as a question I asked about a year ago, however I am now targeting RHEL7 and Bash 4.2.46.
I am writing scripts to install packages from archive files, checking if the package is already installed first. I have the information for each package file in a config file like so:

declare -A package_a=([name]="utility-blah" [ver]="2.4.1")
declare -A package_b=([name]="tool-bleh" [ver]="1.3.9")
# and so on and so forth

My various install scripts source this config file to get package information. Each script contains an array of the packages to be installed. I would like to iterate over this array and install the package named. Ideally, the meat of this loop is in some function so I don’t have to rewrite it in each script. In Ubuntu 18 with Bash 4.4, I was able to include this function in the config file like so:

function install_package()
{
  # dereference hashmap variable
  declare -n package="$1"
  if dpkg --list ${package[name]}; then
    echo "${package[name]} is installed"
  else
    dpkg -i $pathToPackages/${package[name]}_${package[ver]}.deb
  fi
}

This leaves only the loop for the actual script, which looks like this:

source packages.config
source functions.config
declare -a packageList=("package_a" "package_b" "package_d")
for package in ${packageList[@]}; do
  install_package $package
done

This worked perfectly for me on Bash 4.4. Unfortunately, the declare -n option was added in Bash 4.3, and as I am now targeting Bash 4.2, the nameref solution no longer works. Is there a way I can have this same behavior where the script will dereference the package variable? I’ve tried using indirection as this post suggests, but I don’t think ${!package[name]} works the way I want it to.
Is it possible to achieve the same functionality without using declare -n?

2

Answers


  1. Add the index to your indirection variable:

    $ declare -A package_a=([name]="utility-blah" [ver]="2.4.1")
    $ var="package_a[ver]"
    $ echo "${!var}"
    2.4.1
    

    This works on Bash 4.2.45(1)

    Login or Signup to reply.
  2. Can this achieve what you expected ?

    declare -A packages=([package_a]="utility-blah:2.4.1"
                         [package_b]="tool-bleh:1.3.9")
    
    function install_package {
      declare package="${packages[$1]}"
      declare name="${package%:*}" version="${package#*:}"
      if dpkg --list $name; then
        echo "$name is installed"
      else
        dpkg -i $pathToPackages/${name}_$version.deb
      fi
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search