2017-02-22 19 views
0

Я пытаюсь построить функцию zsh, которая возвращает результат на основе временного интервала. Первоначально условие «Ты жаждет» верно, но после изменения переменной thirsty через командную строку и установки ее в значение false, выполняется инструкция initial if, но переменная thirsty в ней не изменяет global variable thirsty. Есть ли способ изменить глобальную переменную thirsty?Невозможно изменить глобальную переменную в функции, используемой для запроса zsh

thirsty= 
last_time= 

drink_water() { 
echo -n "$thirsty" 

    if [[ $thirsty == false ]]; then 
    last_time="$[$(date +%s) + 10]" 
    thirsty=true 
    echo -n "${last_time} $(date +%s) ${thirsty}" 

    elif [[ $[last_time] -lt $(date +%s) ]]; then 
    echo -n " You're thirsty" 
    fi 

} 
+0

(BTW, 'echo -n' на самом деле плохая форма - [спецификация POSIX для' echo'] (http://pubs.opengroup.org/onlinepubs/9699919799/utilities/echo.html) поведение ярлыков, когда '-n' предоставляется как определенный реализацией, то есть разные оболочки могут делать разные вещи с помощью' echo -n'. Если вы хотите что-то * гарантированное * напечатать точную строку без новой строки, используйте строку 'printf '% s' "', см. также раздел ИСПОЛЬЗОВАНИЕ ПРИМЕНЕНИЯ вышеупомянутой ссылки). –

+0

Говоря прямо на вопрос: ** Все переменные оболочки глобальны, если вы явно не указали их иначе **. Вот почему в этом вопросе нужен явный регенератор - код, который кто-то может копировать, вставлять и запускать без изменений, чтобы увидеть поведение для себя. –

+0

У меня есть другая функция 'spacehip_prompt', которая вызывает эту функцию. И затем, в конце концов, у меня есть 'PROMPT = '$ (spaceship_prompt)'' –

ответ

2

Поскольку ваш код на самом деле вызывается из:

PROMPT='$(drink_water)' 

... все это содержит проложена в подпроцесс порождал в рамках этой операции подстановки команд ($() является «подстановки команд» : Он создает новый подпроцесс, запускает код, указанный в этом подпроцессе, и считывает вывод подпроцесса). Когда этот подпроцесс выходит, переменные - даже глобальные переменные - сделанные в рамках подпроцесса теряются.

Если вы поместили код обновления непосредственно внутри функции precmd, он будет запущен до того, как будет напечатано каждое приглашение, но без вмешательства подстановки команд. То есть:

precmd() { 
    local curr_time=$(date +%s) # this is slow, don't repeat it! 
    if [[ $thirsty = false ]]; then 
    last_time="$((curr_time + 10))" 
    thirsty=true 
    PROMPT="$last_time $curr_time $thirsty" 
    elif ((last_time < curr_time)); then 
    PROMPT=" You're thirsty" 
    fi 
} 

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

+0

Это, кажется, работает хорошо, но позволяет сказать, что у меня есть еще несколько функций, которые производят некоторые другие разные выходы для ' PROMPT', то как мне начать установку 'PROMPT' на вывод всех этих функций. Поскольку эта функция явно добавляет вывод в 'PROMPT'. –

+0

Это, прямо, выходит за рамки этого вопроса. –

+0

Тем не менее, я предлагаю разделить вашу логику на отдельные функции с вашего вида. То есть, сделайте обновления в одной функции, которую вы вызываете из основной оболочки, и сгенерируйте строку для отображения из отдельной функции, которую вы вызываете в подстановке команд. ** Однако **, этот совет предоставляется на основе «за то, что он стоит, без каких-либо последующих развлечений», и любых попыток сделать это [вопросом хамелеона] (http://meta.stackexchange.com/questions/ 43478/exit-strategy-for-chameleon-questions) будут нахмуриться. –