Lst.sh – Portable Shell Array Library
lonkamikaze.github.io
lonkamikaze.github.io
You immediately notice that the code uses local which POSIX mentions in a table of reserved commands that all produce unspecified results. You can't have local in a POSIX-confirming script even if you write your own function by that name.
While that could still be portable to a few shells, the $'...' Bash extension makes it less so.
If those things are acceptable, why not assume that the shell has Korn-shell-style arrays.
Almquist allows the local keyword, in violation of the POSIX standard. The wiki says that this is the only extension.
The original article's motivation is for Almquist running under FreeBSD. Almquist is also used in Busybox with a few bash-compatibilty adjustments. However, there are other pure POSIX shells out there, and it is worth adhering to the standard.
Almquist is also much faster than bash, so speed joins compatibility as factors for standard adherence.
local is not in violation of the POSIX standard; it's listed there precisely because it's known extension. The behavior is unspecified; the shells are free to specify it.
What you write will not run in Almquist or other POSIX shells, but don't let that stop you... until it does.
For the practical concern of portability, none of these are compliant, no matter our protests otherwise. They fail.
"The following words may be recognized as reserved words on some implementations (when none of the characters are quoted), causing unspecified results: [[, ]], function, select."
I think that portability and speed were greater concerns. There were many support tickets asking for bash to be restored as /bin/sh.
parr_add () { # $1:array $2:value
eval parr_c=${1}_c
parr_c=$((0+$parr_c))
eval ${1}_${parr_c}=\"$2\"
parr_c=$((1+$parr_c))
eval ${1}_c=$parr_c
unset parr_c
}
I could call this function from a loop that reads the password file: IFS=:
while read user pw uid gid comm home shell <&9
do parr_add acc "$user"
done 9< /etc/passwd
Then, I could access these "array elements" in a loop: count=0
while [ $acc_c -gt $count ]
do eval user=\$acc_$count
printf %s\\n "$user"
count=$((1+count))
done
Example run: $ ./parr.sh | head -5
root
bin
daemon
adm
lp
It isn't that hard to survive without arrays.Is the $'\n' construct actually portable? I cannot find it in Shell Command Language spec [0].
0: https://pubs.opengroup.org/onlinepubs/9699919799/utilities/V... .
local IFS