Search code examples
shellexportkshtypesetpdksh

Is there an explanation of the difference between export and typeset in combination with nested function calls in a KornShell script?


I have encountered an issue with KornShell (ksh) scripts running differently on ksh88 & ksh93 wherein functions which call functions handle differently, variables declared with typeset and export. Here is an example script that highlights the difference:

#!/bin/ksh
# example.ksh: highlights differences between typeset and export on ksh93
function inner
{
  echo "  Inside inner, before assignment, TEST_VALUE=[$TEST_VALUE]"
  TEST_VALUE=abc
  echo "  Inside inner, after assignment, TEST_VALUE=[$TEST_VALUE]"
}
function outer_typeset
{
  typeset TEST_VALUE
  echo "Inside outer_typeset, before call of inner, TEST_VALUE=[$TEST_VALUE]"
  inner
  echo "Inside outer_typeset, after call of inner, TEST_VALUE=[$TEST_VALUE]"
}
function outer_typeset_x
{
  typeset -x TEST_VALUE
  echo "Inside outer_typeset_x, before call of inner, TEST_VALUE=[$TEST_VALUE]"
  inner
  echo "Inside outer_typeset_x, after call of inner, TEST_VALUE=[$TEST_VALUE]"
}
function outer_export
{
  export TEST_VALUE
  echo "Inside outer_export, before call of inner, TEST_VALUE=[$TEST_VALUE]"
  inner
  echo "Inside outer_export, after call of inner, TEST_VALUE=[$TEST_VALUE]"
}

outer_typeset
unset TEST_VALUE
echo
outer_typeset_x
unset TEST_VALUE
echo
outer_export

The result when run on a Linux box running ksh93 follows:

$ echo ${.sh.version}
Version M 1993-12-28 r

$ ./example.ksh
Inside outer_typeset, before call of inner, TEST_VALUE=[]
  Inside inner, before assignment, TEST_VALUE=[]
  Inside inner, after assignment, TEST_VALUE=[abc]
Inside outer_typeset, after call of inner, TEST_VALUE=[]

Inside outer_typeset_x, before call of inner, TEST_VALUE=[]
  Inside inner, before assignment, TEST_VALUE=[]
  Inside inner, after assignment, TEST_VALUE=[abc]
Inside outer_typeset_x, after call of inner, TEST_VALUE=[]

Inside outer_export, before call of inner, TEST_VALUE=[]
  Inside inner, before assignment, TEST_VALUE=[]
  Inside inner, after assignment, TEST_VALUE=[abc]
Inside outer_export, after call of inner, TEST_VALUE=[abc]

As you can see when TEST_VALUE is typeset, the value of TEST_VALUE set in inner is lost when control returns to the outer function. When TEST_VALUE is declared via export, the value set in inner is retained when control returns to outer.

Since there is not a new processes invoked when the outer function calls the inner function, I do not see why export should be used in order for the variable to keep scope in the sub function. Also I have noted that typeset -x behaves the same as typeset whereas I would have expected typeset -x to be equivalent to export.

When I run this program on a machine running ksh88 (AIX, Solaris, HP-UX) or pdksh (Linux) or MKS ksh, typeset, typeset -x, and export behave the same in this example.

For now I have changed typeset to export in order to provide compatibility on ksh93 for the programs using similar code that were developed and tested on ksh88.

Perhaps this is a ksh93 defect?


Solution

  • Your script has calls to inner and inner_function but the latter is not defined. Is this just a typo in the question or does your actual script have this error also?

    The behavior you show in your output is correct.

    Try changing the definition of outer_typeset_x from function outer_typeset_x { to outer_typeset_x () { and you'll see that the output will be the same for it as for outer_export.