typeset
- этоprivate
(ksh93, использующий статическую область видимости, такую как perl
my
, а не local
, которая выполняет динамическую область видимости )только для функций, которые объявлены с использованием стиля определения функции ksh:
function foo {
typeset var=whatever
...
}
С синтаксисом Bourne (или с командой .
(, которая, кстати, также может использоваться в функциях стиля ksh -)), нет области видимости (, за исключением $1
, $2
... $#
конечно ). Таким образом, можно использовать функции стиля Bourne -для получения значения или изменения значения или типа переменной в родительском контексте (, хотя typeset -n
также можно использовать для этого со стилем ksh -.
В ksh88 typeset
выполнял динамическую область видимости как со стилем определения функции ksh, так и со стилем определения функции Борна. По словам Дэвида Корна, POSIX не определял область видимости переменных ksh на том основании, что она была динамической(признанной низшей ), поэтому он изменил ее на статическую область видимости дляksh93
(полной перезаписи ).
Но тем временем другие оболочки реализовали переменную область видимости, и все они использовали динамическую область видимости для имитации ksh88.
zsh
теперь имеет ключевое слово private
для области видимости, аналогичной ksh93
, в дополнение к local
/ typeset
с динамической областью видимости, как в ksh88
.
Чтобы увидеть разницу между статической и динамической областью видимости, сравните:
"$shell" -c 'function f { typeset a=1; g; echo "$a"; }
function g { echo "$a"; a=2; }
a=0; f'
Который с $shell
== ksh93
выводит:
0
1
И с выходами ksh88
или bash
:
1
2
zsh
:
$ zsh -c 'zmodload zsh/param/private
f() { private a=1; g; echo $a;}
g() { echo $a; a=2; }
a=0; f'
0
1
Чтобы иметь возможность использовать локальную область видимости в коде, переносимом на bash
, zsh
, ksh88
ksh93
, pdksh
, yash
или dash
/FreeBSD
sh, вы можете сделать:
[ -n "$BASH_VERSION" ] && shopt -s expand_aliases
alias shdef= kshdef='#'
if type typeset > /dev/null 2>&1; then
alias mylocal=typeset
if (a=1; f() { typeset a=2; }; f; [ "$a" = 2 ]); then
alias shdef='#' kshdef='function'
fi
else
alias mylocal=local
fi
А затем объявите свои функции как:
kshdef foo
shdef foo()
{
mylocal var
var=value
...
}
В любом случае существует много различий между поведением тех local
в различных оболочках.Помимо упомянутого выше динамического и статического соображений, существует вопрос о том, получают ли переменные изначально неустановленное или пустое значение или наследуют значение из родительской области. И есть взаимодействие с readonly
, unset
, независимо от того, является ли local
/ typeset
ключевым словом или встроенным (, влияет на обработку split+glob )...
Существуют и другие последствия использования определения функции стиля ksh -в ksh93
, подробности см. на справочной странице.
sh
. Программы обычно записывают сообщения об ошибках в поток ввода-вывода «стандартная ошибка»; «stderr» для краткости. Если вы будете искать этот термин, вы получите миллионы результатов; короткое объяснение заключается в том, что существует stderr, поэтому сообщения об ошибках могут и будут перейти на экран при перенаправлении «стандартный вывод» («stdout» ), как в гипотетической команде типа
umount /dev/sdb1 > um.result.txt
И вы можете видеть, как это происходит; сообщение об ошибке появляется на вашем экране даже если вы пытаетесь зафиксировать его в переменной.
Такой же короткий ответ – использовать 2>&1
чтобы объединить поток stderr с потоком stdout, поэтому
foo=$(umount /dev/sdb1 2>&1)
зафиксирует сообщение об ошибке в переменной.
Другой подход, , предложенный jordanm в комментарии , это посмотреть статус выхода. Вариации на эту тему включают :
umount /dev/sdb1 || complain to user
if ! umount /dev/sdb1 then complain to user fi
umount /dev/sdb1 2> /dev/null || complain to user
foo=$(umount /dev/sdb1 2>&1) || complain to user using "$foo"