Есть ли объяснение разницы между экспортом и набором в сочетании с вызовами вложенных функций в скрипте KornShell? - PullRequest
2 голосов
/ 04 июня 2010

Я столкнулся с проблемой со скриптами KornShell (ksh), работающими по-разному на ksh88 и ksh93, в которых функции, вызывающие функции, обрабатывают по-разному, переменные, объявленные с помощью typeset и export.Вот пример сценария, который подчеркивает разницу:

#!/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

Результат при запуске на Linux-машине с ksh93 выглядит следующим образом:

$ 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]

Как вы можете видеть, когда TEST_VALUE набирается,значение TEST_VALUE, установленное во inner, теряется, когда управление возвращается к внешней функции.Когда TEST_VALUE объявляется с помощью экспорта, значение, установленное во внутреннем элементе, сохраняется, когда управление возвращается к внешнему.

Поскольку нет новых процессов, вызываемых, когда внешняя функция вызывает внутреннюю функцию, я не понимаю, почему экспорт должениспользоваться для того, чтобы переменная оставила область действия в подфункции.Также я заметил, что typeset -x ведет себя так же, как typeset, тогда как я ожидал, что typeset -x будет эквивалентен экспорту.

Когда я запускаю эту программу на машине с ksh88 (AIX, Solaris, HP-UX) или pdksh (Linux) или MKS ksh, typeset, typeset -x и export ведут себя одинаково в этом примере.

На данный момент я изменил typeset для экспорта, чтобы обеспечить совместимость на ksh93 для программиспользуя аналогичный код, который был разработан и протестирован на ksh88.

Возможно, это дефект ksh93?

Ответы [ 2 ]

1 голос
/ 04 июня 2010

Ваш скрипт имеет вызовы inner и inner_function, но последний не определен. Это просто опечатка в вопросе или в вашем подлинном скрипте тоже есть эта ошибка?

Правильное поведение, которое вы показываете в выходных данных.

Попробуйте изменить определение outer_typeset_x с function outer_typeset_x { на outer_typeset_x () {, и вы увидите, что вывод будет таким же, как и для outer_export.

1 голос
/ 04 июня 2010

В руководстве ksh93 есть что сказать о typeset:

При вызове внутри функции, определенной с синтаксисом имени функции, создается новый экземпляр переменной vname, а значение и тип переменной восстанавливаются после завершения функции.

А это около export:

указанные имена помечены для автоматического экспорта в среду выполняемых впоследствии команд.

В частности, ничего не восстанавливается при использовании экспорта внутри функции.

Кажется вероятным, что typeset предназначен для обеспечения функциональности, предоставляемой "локальными переменными процедуры" в других языках. Я бы не назвал это дефектом дизайна.

...