RFC: proposed new builtin for /bin/sh (associative arrays)

Luigi Rizzo rizzo at icir.org
Fri Oct 31 01:43:35 PST 2003

[Not sure what is the appropriate forum to discuss this, so
please redirect the discussion if you know where. I have Bcc-ed
a few /bin/sh committers]

I am trying to implement, in the most unintrusive way, something
resembliung associative arrays in /bin/sh.  I am not interested in
syntactic sugar, so i am happy to use something like _ as a separator
between the array basename and the "index", i.e.

	foo_red foo_green foo_blue

would be part of the same array. And, as a first step, I am also
happy to be limited to [0-9A-Za-z_]+ as "index" values.
So all it was necessary was a command to enumerate the indexes
of an array, which is implemented by the attached patch, and
can be used as follows:

	for i in `indexes foo_`
		eval x=\$foo_$i
		echo "variable foo_$i has value $x"

(basically, "indexes xyz" lists the remaining part of all variable
names that start with xyz. As a possibly useful side effect,
indexes "" lists all variable names, which i believe is not an
available sh function -- and i find it strange since we can
list the names of readonly and export-ed variables with the
"readonly" and "export" builtins).

Any comments ? Is this interesting enough to be committed
(with a proper manpage description) ?
I could provide a flag to "indexes" to return the values instead
of the names, but i believe this form is more useful.

The next step would be to allow arbitrary strings as indexes, but
that would be trickier because it would change the syntax for
variable names (e.g. allowing \[.*\] as the last part of a variable


Index: builtins.def
RCS file: /home/ncvs/src/bin/sh/builtins.def,v
retrieving revision
diff -u -r1.7.2.2 builtins.def
--- builtins.def	27 Aug 2002 01:36:28 -0000
+++ builtins.def	30 Oct 2003 09:02:37 -0000
@@ -69,6 +69,7 @@
 fgcmd -j	fg
 getoptscmd	getopts
 hashcmd		hash
+indexes		indexes
 jobidcmd	jobid
 jobscmd		jobs
 #linecmd		line
Index: var.c
RCS file: /home/ncvs/src/bin/sh/var.c,v
retrieving revision
diff -u -r1.15.2.2 var.c
--- var.c	27 Aug 2002 01:36:28 -0000
+++ var.c	31 Oct 2003 09:06:27 -0000
@@ -602,6 +602,28 @@
 	return 0;
+indexes(int argc, char **argv)
+	struct var **vpp;
+	struct var *vp;
+	char *p, *q;
+	if (argc != 2)
+		error("indexes require one argument");
+	for (vpp = vartab ; vpp < vartab + VTABSIZE ; vpp++) {
+		for (vp = *vpp ; vp ; vp = vp->next) {
+			for (p = vp->text, q = argv[1];
+				    *p != '=' && *p == *q; p++, q++)
+				;
+			if (*q != '\0')
+				continue;	/* not found */
+			while (*p != '=')
+				out1c(*p++);
+			out1c('\n');
+		}
+	}
  * The "local" command.

More information about the freebsd-hackers mailing list