Вопрос или проблема
Мне просто интересно различие между вызовом функции $(one_function)
и one_function
в bash shell script.
Когда я устанавливаю переменную PS1
в ~/.bashrc
, я не могу вызвать функцию с помощью one_func
например:
export PS1="\n\[\e[31m\] \$(one_func) # это работает
export PS1="\n\[\e[31m\] one_func # это не работает
В отличие от доступа к переменным, функции вызываются по имени без использования ‘$
‘ перед именем.
Возможно, вы запутались, как в командной строке вы можете определить функцию и вызвать ее по имени, но в вашем PS1
вы должны были поместить команду в скобки, предварив ее ‘\$
‘. Заключение имени функции в ‘$(
‘ и ‘)
‘ вызывает замену всей ‘$(function)’ на стандартный вывод этой функции. Добавление обратной косой черты перед этим вызывает выполнение/запуск функции каждый раз, когда оболочка хочет вывести $PS1
. Если бы вы не добавили обратную косую черту, функция была бы вызвана только один раз, при первом определении PS1
, и какой бы ни был вывод функции в этот первый раз, он навсегда оставался бы в вашем приглашении PS1
.
Когда вы вызываете $(one_func)
, это исполнит функцию и вернет вывод. Так, если вы скажете, например:
var=$(ls)
это сохранит вывод команды ls
(т.е. список файлов в текущем каталоге) в переменную $var
. В то время как команда:
var=ls
просто установит значение $var
равным “ls”.
Кстати, вызов функции в bash происходит так же, как выполнение команды.
Просто чтобы дополнить вышеизложенное. очень полезная информация… та же идея применима при вложении функций и вызове исполняемых файлов…
PS1="# \e[1;30m\u\e[0;37m@\h: \e[1;31m\w\e[31m >\e[1;30m \t \e[1;33m [ \$(kmg \$(totalfilesize.sh)) ]\e[m\n"
“kmg” — это функция bash, которую я определил, и с помощью этого синтаксиса ей передается аргумент из вывода скрипта “totalfilesize.sh”
\$(kmg \$(totalfilesize.sh))
Если вам интересно, totalfilesize вычисляет размер файлов в текущем каталоге, а kmg преобразует строку (в байтах) в удобочитаемые b, MB, gB и т.д.
Ответ или решение
Чтобы понять, как вызвать функцию в bash-скрипте, необходимо углубиться в отличия между различными способами вызова и их применимостями в различных сценариях. В вашем вопросе упоминается различие между $(one_function)
и one_function
в контексте bash-скриптов, особенно в случае настройки переменной PS1
.
Теория
В bash-скриптах функции определяются и вызываются поимённо, без необходимости использовать символ $
. Однако, когда мы хотим получить текстовое значение, генерируемое функцией, часто применяются команды подстановки $()
или обратные кавычки `
. Эти конструкции запускают команду, указанную внутри них, и заменяют их вызов выводом этой команды.
Так, $(one_func)
выполнит функцию one_func
, захватит её стандартный вывод и подставит на место вызова. Применение команды подстановки полезно, когда требуется динамически обновлять значение переменной, как это бывает в PS1
. В отличие от этого, просто one_func
вызовет функцию, но её вывод не будет подставлен в строку.
Пример
В bash, если вы объявляете функцию, например:
one_func() {
echo "Hello, World!"
}
вы можете вызвать функцию напрямую в скрипте:
one_func # Эта команда выведет "Hello, World!" в терминале.
Однако, чтобы захватить вывод этой функции и использовать его, например, для присвоения переменной, необходимо использовать команду подстановки:
var=$(one_func)
echo $var # Эта команда также выведет "Hello, World!", но сначала её значение будет сохранено в переменной `var`.
В контексте настройки переменной PS1
, эта разница становится критически важной. Если просто использовать имя функции в PS1
, например:
export PS1="\n\[\e[31m\] one_func"
То bash трактует one_func
как просто текст, поэтому вызова функции на самом деле не происходит. Однако конструкция:
export PS1="\n\[\e[31m\] \$(one_func)"
действительно вызывает функцию и подставляет её вывод в строку PS1
, создавая динамическую командную строку, которая обновляется с каждым её выводом.
Применение
При настройке командной строки с динамическими данными, такими как время, текущее состояние системы или информация о пользователе, полезно использовать функции, которые выполняются и возвращают значения непосредственно перед показом командной строки. Это достигается через командную подстановку.
Пример применения более сложной настройки:
PS1="[\u@\h \W]\$(my_prompt_function) > "
Здесь my_prompt_function
может быть функцией, которая возвращает специфическую информацию, например, текущий git branch или статус системы, и её вывод будет интегрирован в вашу командную строку.
Ещё один пример использования пользовательских функций в псевдографике:
PS1="# \e[1;30m\u\e[0;37m@\h: \e[1;31m\w\e[31m >\e[1;30m \t \e[1;33m [\$(kmg \$(totalfilesize.sh))]\e[m\n"
Здесь kmg
— это функция bash, которая принимает аргументом вывод другого скрипта totalfilesize.sh
, что позволяет динамично выводить размер файлов в удобочитаемом формате.
Заключение
Использование функций и их вызов в bash-скриптах предоставляет мощные инструменты для автоматизации и динамической настройки окружения командной строки. Важно помнить о различиях между вызовом функций напрямую и через командную подстановку, чтобы корректно использовать их возможности в зависимости от контекста. Через понимание этих механизмов можно значительно упростить работу с bash-скриптами и расширить их функционал до уровня интерактивных и персонализированных рабочих инструментов.