Итак, я начал использовать zsh
. Мне нравится все в порядке. Это выглядит очень круто и гладко, и тот факт, что текущий рабочий каталог и фактическая командная строка находятся на разных строках, это хорошо, но в то же время я замечаю, что это zsh
может быть немного медленнее, чем bash
, особенно при печати текста в экран.
Больше всего мне понравилось то, что он zsh
был «обратно совместим» со всеми функциями, которые я определил в своих .bashrc
.
Хотя одна схватка. Все функции работают отлично, но я не могу понять, как работает система экспорта.
У меня были .bashrc
экспортированы некоторые из этих функций, чтобы я мог использовать их в другом месте, например, в скриптах и внешних программах export -f
.
В zsh об экспорте даже не говорят. Это автозагрузка? Эти две вещи одинаковы? Мне тяжело понять это.
источник
Ответы:
Переменные окружения, содержащие функции, являются взломом bash. У Zsh нет ничего похожего. Вы можете сделать что-то подобное с несколькими строками кода. Переменные окружения содержат строки; более старые версии bash, до обнаружения Shellshock , хранили код функции в переменной, имя которой совпадает с именем функции, а за значением
() {
следует код функции, после которого следует}
. Вы можете использовать следующий код, чтобы импортировать переменные с этой кодировкой и попытаться запустить их с настройками, подобными bash. Обратите внимание, что zsh не может эмулировать все функции bash, все, что вы можете сделать, это немного приблизиться (например, чтобы$foo
разделить значение и расширить подстановочные знаки, а также сделать массивы на основе 0).(Как отметил Стефан Шазелас , первооткрыватель Shellshock, более ранняя версия этого ответа могла выполнить произвольный код на этом этапе, если определение функции было некорректно. это может быть функция, импортированная из среды.)
Версии bash после Shellshock кодируют функции в среде, используя недопустимые имена переменных (например
BASH_FUNC_myfunc%%
). Это затрудняет их надежный анализ, поскольку zsh не предоставляет интерфейс для извлечения таких имен переменных из среды.Я не рекомендую делать это. Полагаться на экспортируемые функции в скриптах - плохая идея: это создает невидимую зависимость в вашем скрипте. Если вы когда-либо запускаете свой сценарий в среде, в которой нет вашей функции (на другом компьютере, в задании cron, после изменения файлов инициализации оболочки…), ваш сценарий больше не будет работать. Вместо этого сохраните все свои функции в одном или нескольких отдельных файлах (что-то вроде
~/lib/shell/foo.sh
) и запустите свои сценарии, импортировав функции, которые он использует (. ~/lib/shell/foo.sh
). Таким образом, если вы изменитеfoo.sh
, вы можете легко найти, какие сценарии полагаются на него. Если вы скопируете скрипт, вы легко сможете узнать, какие вспомогательные файлы ему нужны.Zsh (и ksh перед ним) делает это более удобным, предоставляя способ автоматической загрузки функций в сценарии, где они используются. Ограничением является то, что вы можете поместить только одну функцию в файл. Объявите функцию как автозагрузку и поместите определение функции в файл, именем которого является имя функции. Поместите этот файл в каталог, указанный в
$fpath
(который вы можете настроить черезFPATH
переменную окружения). В вашем скрипте объявите автозагрузку функций с помощьюautoload -U foo
.Кроме того, zsh может компилировать скрипты, чтобы сэкономить время на анализ. Звоните,
zcompile
чтобы скомпилировать скрипт. Это создает файл с.zwc
расширением. Если этот файл присутствует, тоautoload
загрузит скомпилированный файл вместо исходного кода. Вы можете использоватьzrecompile
функцию для (пере) компиляции всех определений функций в каталоге.источник
bash
что и шелл-шок (не проверяет, что содержимое переменной является только определением функции, и обрабатывает любое имя переменной, напримерHTTP_HOST
илиLC_X
). Хороший ответ иначе.zsh -c 'functions[f]=$VAR'
это анализируется , даже еслиf
функция не вызывается). Решение состоит в том, чтобы рассматривать только переменные, имена которых следуют за зарезервированным шаблоном, как те$BASH_FUNC_x%%
, но, как вы говорите,zsh
не имеют API для их перечисления или извлечения. Вам нужно позвонить,perl
например.Если вы поместите объявление своей функции в .zshenv , ваша функция будет использоваться из скрипта без каких-либо усилий.
источник
.zshenv
и оно замедляет каждый вызов zsh, анализируя большой объем кода, который никогда не используется. Кроме того, это не то же самое, что экспорт функции, как экспортируемая переменная, экспортированная функция доступна только для дочерних процессов. В то время как материал, который вы вставляете,.zshenv
доступен каждому zsh..zshenv
, то все ваши скрипты будут полностью непереносимыми. Обычно сценарии могут зависеть друг от друга, и это нормально, вы распространяете их вместе. Но если они зависят от наличия специальных функций.zshenv
, никто не захочет их использовать, или они должны будут вызываться со специальными функциямиZDOTDIR
, предотвращающими выполнение ваших собственных функций.zshenv
. Это будет боль.