Most shells, including
bash,
ksh88 and
pdksh, implement a flat variable namespace. According to
Dave Korn, one of the lessons learned from
UNIX is that a hierarchical namespace is better than a flat namespace. For this reason, amongst others, a hierarchical variable namespace was implemented by him in
ksh93, with . (dot) as the separator for each level of the hierarchy. This expanded variable namespace enabled the implementation of an aggregate definition for a shell variable to include
subvariables. Such shell variables are called
compound variables. Not much appears to have been written about
compound variables to date and, as usual, the
ksh93 man page is terse on the subject. This post will try to explain
compound variables in detail and demonstrate how useful they can be in when dealing with structured data.
As in
bash,
ksh88, and
pdksh, a variable in
ksh93 is defined by a
name=value pair.
$ myvar=10
$ print $myvar
10
Now consider the following commands which show how to declare a
compound variable, define
subvariables and interact with those
subvariables.
$ typeset -C myvar # declare 'myvar' as compound variable
$ myvar.x=10 # set subvariable 'x' to 10
$ myvar.y=20 # set subvariable 'y' to 20
$ print $myvar # print definition of compound variable
( x=10 y=20 )
$ print ${myvar.x} # print value of 'x' subvariable
10
$ print ${myvar.y} # print value of 'y' subvariable
20
$ yourvar=( x=10 y=5 ) # declare and define 'yourvar' compound variable
$ print $yourvar
( x=10 y=5 )
$ print $(( yourvar.x * yourvar.y )) # multiply 2 subvariables together.
50
$
A variable with a
. (dot,period) in it’s name is called a
subvariable. However to create a
subvariable, a variable whose name consists of everything up to the period must already exist. Note that variable names that begin with
.sh are reserved for use by
ksh93.
Just as
var='' initializes a simple variable,
var=() does the same for a
compound variable. This is not assigning a value to
var; it is simply declaring that
var is a
compound variable and its value will be defined by all
subvariables of the form
var.*.
You can specify the type of specific
subvariables. For example, to create a
compound variable with a
subvariable named
x of type
integer.
You can have more than one level of
subvariables in a
compound variable. However, you must be careful to first declare the
compound variable otherwise you will get an error.
$ var=
$ var.x.y=2
/bin/ksh93t: var.x.y=2: no parent
$ var=()
$ var.x.y=2
$ print $var
( x=( y=2 ) )
$
You can use
+= word with
compound variables provided the types are compatable. When
+= word is applied to an arithmetic type,
word is added to the current value. When applied to a string variable,
word is appended to the value.
$ var=( str="abc" typeset -i num=12 )
$ var.str+="def"
$ var.num+=12
$ print ${var.}
( typeset -i num=24 str=abcdef )
$
You may be wondering why the value of a
compound variable is outputted in the form that it is. The reason is that value of a
compound variable is intended to be in a form ready for reinput by
ksh93 as shown by the following example.
$ var=( x=2 y=4 )
$ print $var
( x=2 y=4 )
$ print -r "newvar=$var" > file
$ unset var
$ print $var
$ . ./file
$ print $newvar
( x=2 y=4)
$
You can copy
compound variables using the
eval builtin.
$ var=( x=2 y=3 )
$ print $var
( x=2 y=3 )
$ eval "newvar=$var"
$ print $newvar
( x=2 y=3 )
$
You can create a new
compound variable from part of a existing
compound variable.
$ var=( x=1 y=2 )
$ var.y.a=1
$ var.y.b=2
$ var.y.c=3
$ print $var
( x=1 y=2 y=( a=1 b=2 c=3 .=2 ) )
$ eval "newvar=${var.y.}"
$ print $newvar
( a=1 b=2 c=3 .=2 )
$ print -r -- "newvar=${newvar.}"
newvar=(
a=1
b=2
c=3
.=2
)
$
Compound variables can be exported but
subvariables cannot.
$ testvar=( x=12 )
$ echo ${testvar.x}
12
$ export testvar.x
/bin/ksh93: export: testvar.x: invalid export name
$ export testvar
$ env | grep testvar
testvar=(x=12;)
$
One thing you need to be aware of is that
ksh93 also uses the
. (dot) notation to denote what are called
discipline functions. Shell variables in
ksh93 can also behave as active objects rather than as simple storage units by having a one or more functions associated with a variable. These functions are called
discipline functions. A
discipline function is defined like any other function, except that the name for a
discipline function is formed by using the variable name, followed by a
. (dot), followed by the discipline name. Any variable can have
discipline functions defined that are invoked when the variable is referenced or assigned a value. The default set of
discipline functions in
ksh93 is
get,
set, and
unset. Other
discipline functions can be defined via a custom shared library.
Compound variables are currently a work in progress. Some of the examples that I have shown above may not work in future versions of
ksh93. These examples were tested on
ksh93t 2008-07-24.
Well, that is about all you need to get you started using
compound variables. I hope this post has given you some ideas about how useful such variables could be in your future
ksh93 scripts.
1 comments:
1. Copying via "eval" is obsolete - at least in ast-ksh.2008-11-04 you can simply do a a=b to copy the compound variable content from "b" to compound variable "a" (assuming both have been declared as compound variable)
2. Compound variables support the += operator to merge compound variables
Post a Comment