Объем переменных в KSH

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

#!/usr/bin/ksh

splitString() {

    string="[email protected];[email protected];[email protected]"

    oIFS="$IFS"; 
    IFS=';' 
    set -A str $string
    IFS="$oIFS"
}

splitString
echo "strings count = ${#str[@]}"
echo "first : ${str[0]}";
echo "second: ${str[1]}";
echo "third : ${str[2]}";

Теперь echo не печатает значения массива, поэтому я предполагаю, что он имеет какое-то отношение к области определения массива.

Я новичок в сценариях Shell, может ли кто-нибудь помочь мне понять объем переменных в приведенном выше примере?

Ответ 1

Объем переменной по умолчанию - это весь script.

Однако, когда вы объявляете переменную внутри функции, переменная становится локальной для функции, объявляющей ее. Ksh имеет динамическое масштабирование, поэтому переменная также доступна в функциях, которые вызывается функцией, объявляющей переменную. Это подробно описано в разделе о функциях в руководстве. Обратите внимание, что в AT & T ksh (в отличие от pdksh и производных и аналогичных характеристик bash и zsh) это относится только к функциям, определенным с ключевым словом function, а не к функциям, определенным традиционным f () { … } синтаксис. В AT & T ksh93 все переменные, объявленные в функциях, определенных с помощью традиционного синтаксиса, являются глобальными.

Основной способ объявления переменной - это typeset встроенный. Он всегда делает переменную локальную (в AT & T ksh, только в функциях, объявленных с помощью function). Если вы назначаете переменную без объявления ее с помощью typeset, она глобальна.

В документации ksh не указывается, будет ли set -A делать переменную локальную или глобальную, а также другие версии. Под ksh 93u, pdksh или mksh переменная глобальна, и ваш script распечатает значение. У вас, похоже, есть ksh88 или старая версия ksh, где область локальная. Я думаю, что инициализация str вне функции создаст глобальную переменную, но я не уверен.

Обратите внимание, что вы должны использовать локальную переменную для переопределения значения IFS: сохранение в другой переменной не только неуклюже, но и хрупкое, потому что оно не восстанавливает IFS правильно, если оно было отменено. Кроме того, вы должны отключить глобусы, потому что в противном случае, если строка содержит символы globing оболочки ?*\[, и одно из слов соответствует одному или нескольким файлам в вашей системе, оно будет расширено, например. set -A $string где string is a;* приведет к str, содержащему список имен файлов в текущем каталоге.

set -A str
function splitString {
  typeset IFS=';' globbing=1
  case $- in *f*) globbing=;; esac
  set -f
  set -A str $string
  if [ -n "$globbing" ]; then set +f; fi
}
splitString "$string"

Ответ 2

Переменные обычно являются глобальными для оболочки, с которой они определены, с момента их определения.

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

Прочитайте "typeset" и "integer" в man-странице или в книге Korn.