Shell – How to use pseudo-arrays in POSIX shell script

arrayposixshell-script

How to use pseudo-arrays in POSIX shell script?

I want to replace an array of 10 integers in a Bash script with something similar into POSIX shell script.

I managed to come across Rich’s sh (POSIX shell) tricks, on section Working with arrays.

What I tried:

save_pseudo_array()
{
    for i do
        printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/"
    done
    echo " "
}

coords=$(save_pseudo_array "$@")
set -- 1895 955 1104 691 1131 660 1145 570 1199 381
eval "set -- $coords"

I don't comprehend it, that's the problem, if anyone could shed some light on it, much appreciated.

Best Answer

The idea is to encode the list of arbitrary strings into a scalar variable in a format that can later be used to reconstruct the list or arbitrary strings.

 $ save_pseudo_array x "y z" $'x\ny' "a'b"
'x' \
'y z' \
'x
y' \
'a'\''b' \

$

When you stick set -- in front of that, it makes shell code that reconstructs that list of x, y z strings and stores it in the $@ array, which you just need to evaluate.

The sed takes care of properly quoting each string (adds ' at the beginning of the first line, at the end of the last line and replaces all 's with '\'').

However, that means running one printf and sed command for each argument, so it's pretty inefficient. That could be done in a more straightforward way with just one awk invocation:

save_pseudo_array() {
  LC_ALL=C awk -v q=\' '
    BEGIN{
      for (i=1; i<ARGC; i++) {
        gsub(q, q "\\" q q, ARGV[i])
        printf "%s ", q ARGV[i] q
      }
      print ""
    }' "$@"
}
Related Question