LINUX.ORG.RU

bash + local + variable redefinition

 


0

2

Нужно ли повторять local при конструкциях вроде:

f()
{
    local elephants=220
    local elephants=${elephants#0}
}

?

Или достаточно:

f()
{
    local elephants=220
    elephants=${elephants#0}
}

?

В каком случае elephants останутся локальными для фунции f()?

Второго варианта достаточно. local var[=val] объявляет переменную как локальную, если она ещё не существует. А bash при разрешении имён сначала смотрит на локальные переменные.

xaizek ★★★★★
()
Ответ на: комментарий от xaizek

А bash при разрешении имён сначала смотрит на локальные переменные.

Точнее, он осуществляет поиск переменной с конца. Потому первый пример у ТСа валидный, имеют смысл если эти две строки сильно отстоят друг от друга и/или в if-е, тогда произойдёт (пере)объявление переменной с очисткой, и далее будет использоваться последняя.

vodz ★★★★★
()
Ответ на: комментарий от vodz

A можешь объяснить попроще? Как таки делать, как в первом примере или как во втором? Например:

f()
{
    local elephants="elephants"
    local elephants="monkeys"
}

Или второй local не нужен? Строки вроде как сильно отстоят друг от друга.

А тут нужен второй local? Тут вроде сильно не отстоят:

f()
{
    local elephants="elephants1"
    local elephants="elephants2"
}
dissident ★★
() автор топика
Ответ на: комментарий от dissident

A можешь объяснить попроще?

Нет.

Как таки делать, как в первом примере или как во втором?

Если непонятно, ни документация, ни примеры в инете, ни ответы, то объяснять — бесполезно.

vodz ★★★★★
()
Ответ на: комментарий от vodz

Извини, но вот эта фраза очень неясно написана, поэтому просил прояснить:

Потому первый пример у ТСа валидный, имеют смысл если эти две строки сильно отстоят друг от друга и/или в if-е, тогда произойдёт (пере)объявление переменной с очисткой, и далее будет использоваться последняя.

  • Почему в if’е происходит переобъявление переменной? Ни в одном итеративном языке такого не видел.
  • Какие строки? Что значит сильно отстоят? Расстояние Левенштейна? И что конкретно отстоит? Названия переменных или их значения?

Если непонятно, ни документация, ни примеры в инете, ни ответы, то объяснять — бесполезно.

Что касается документации ты, конечно, прав. В оправдание могу сказать лишь, что:

  • No offence taken
  • Я хотел быстро написать скрипт на баше для личных целей и заняться делом, оказалось, что он замороченный больше чем я помнил (например 0009 - это невалидное восьмеричное число, никакого 0о0.. чтобы помочь тому кто пишет скрипт нету)
  • Я читал про само ключевое слово locale, но про употребление его при придании локальной переменной иного значения - нет. Здравый смысл подсказывает, что раз это итеративный язык, то locale надо применить только при «декларации переменной» (первом употреблении) как какой-нибудь const в C. Хотел уточнить, но выгуглю, нет проблем.
dissident ★★
() автор топика
Ответ на: комментарий от dissident

Почему в if’е происходит переобъявление переменной? Ни в одном итеративном языке такого не видел.

Имелось в виду, что может быть развесистая логика, которая для временных переменных вызывает свой local. Это ничем не страшно, так как не будет расхода памяти на переменные, так как в одной функции один контекст. Но иногда очень полезно, так как помимо обнуления, local позволяет нарисовать присваивание такое, какое может сделать только eval. Например, копирование массива:

local -a '_copy=("${'$1'[@]}")'
Этим знатоки bash-а пользуются.

vodz ★★★★★
()
Последнее исправление: vodz (всего исправлений: 1)
Ответ на: комментарий от vodz

Я просто писал говноскрипт лично для себя. Неужели нельзя было не лезть в джунгли к въетнамцам, а ответить одним предложением как тут:

Once you’ve defined a local variable you can assign it normally

(c) https://stackoverflow.com/questions/22527325/assign-local-variable-from-function-in-linux-bash-a-new-value

Меньше твего и моего времени заняло бы.

PS Я не наезжаю и не обижаюсь, просто какова семантическая информация была в твоем сообщении? Время только потеряли. Но я благодарен за твое объяснение, попробую его переварить. Если я правильно понял все сводится к тому, что local в самом глубоком scope перекрывает local с тем же названием переменной в scope выше, при этом используя ту же память (правда куда он сует старое значение, чтобы его вернуть при выходе из самого глубого scope, где есть локальная переменная с таким же названием, как локальнач переменная выше?) Куда-то же он старое значение должен деть. чтобы его восстановить при выходе из самого глубокого scope’а. А значит по итогу памяти займется столько же. Если неправильно понял - сорри.

PPS Впрочем я подумал пару минут и понял. что я не прав. Не полезешь в джунгли ничего кроме своей деревни с аборигенками с обвисшими сиськами знать не будешь. Так что sorry.

dissident ★★
() автор топика
Последнее исправление: dissident (всего исправлений: 3)
Ответ на: комментарий от dissident

правда куда он сует старое значение, чтобы его вернуть при выходе из самого глубого scope, где есть локальная переменная с таким же названием, как локальнач переменная выше?

Никуда не суёт, в том то и суть.

if expr1; then
 local tmp=XXX
 expr_with_tmp
fi
# другой код, много
if expr2; then
 local tmp=XXX
 expr_with_tmp
fi
Вот в этом коде понятное дело, что могут выполниться либо первый либо второй либо оба if-а (ни одного — не интересно и опустим). Переменная объявится или в одном месте или в двух. Но ничего страшного в этом нет. Если убрать local во втором месте, то, если первый if не сработает, tmp перекроет глобальный tmp, что — плохо. Так понятнее? В этом и было изначальное возражение, что local несколько раз на одну переменную в if-ах бывает нужен.

vodz ★★★★★
()
Последнее исправление: vodz (всего исправлений: 5)
Ответ на: комментарий от vodz

понятно!

Спасибо за потраченное на меня время.

dissident ★★
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.