Как определить функцию Bash, которая может использоваться различными сценариями

: встроенный также полезно с Bash, "присваивают значения по умолчанию" расширение оболочки, где расширение часто используется только для побочного эффекта, и расширенное значение выброшено:

# assign FOO=bar iff FOO is unset
: ${FOO:=bar}
13
04.02.2013, 18:04
3 ответа

~/.bash_profile и ~/.bashrc не читаются сценариями, и функции не экспортируются по умолчанию. Для этого можно использовать export -f как так:

$ cat > script << 'EOF'
#!/bin/bash
foo
EOF
$ chmod a+x script
$ ./script
./script: line 2: foo: command not found
$ foo() { echo "works" ; } 
$ export -f foo
$ ./script
works

export -f foo мог также быть призван ~/.bash_profile сделать эту функцию доступной для сценариев после входа в систему. Предупредите это export -f не является портативным.

Лучшее решение состояло бы в том, чтобы получить файл, содержащий функциональное использование . file. Это намного более портативно, и не полагается на Вашу среду, настраиваемую конкретным способом.

9
27.01.2020, 19:53
  • 1
    , почему не только объявляют функцию как function myFunction { ... } в ~/.bash_profile и Вы хороши для движения? –  amphibient 04.02.2013, 18:34
  • 2
    Если бы я понял правильно Ваш ответ (относительно определения источника файла с функцией), то это означало бы, что я должен получить файл явно в каждом сценарии, который является в значительной степени раздражающим. Это не намного менее сложно, чем просто вставка копии сама функция в каждом сценарии. Я сохранил бы некоторые строки, уверенные, но это - все. Однако export решение, кажется, работает правильно.Спасибо. –  Onturenio 04.02.2013, 18:53
  • 3
    @foampile, это точно, что я сделал и не работаю при вызывании функции из сценария. –  Onturenio 04.02.2013, 18:56
  • 4
    @Onturenio: второй метод, @chris-down предложенный, действительно лучше: 1), Когда кто-то прочитал сценарий, они знают, что требуются некоторых foo функция от некоторых file 2) Можно лучше управлять содержанием этого file чем удостоверяются, что оболочка вызова не изменилась foo прежде, чем вызвать Ваш сценарий. Вы могли включить проверки безопасности file для проверки это не вмешивается, например. (не легкий, но возможный). (хорошо, Вы могли также сделать, они проверяют определенную функцию нечто..., но Вы получаете мой дрейф ^^, я думаю, что метод 2 является более чистым.) 3) file будет только содержать то, что необходимо, не больше. –  Olivier Dulac 04.02.2013, 19:25

.bashrc только читается интерактивными оболочками. (На самом деле это - упрощение: удар является изворотливым в этом отношении. Bash не читает .bashrc если это - оболочка входа в систему, интерактивная или нет. И существует исключение даже к исключению: если родительский процесс удара rshd или sshd, затем удар действительно читает .bashrc, является ли это интерактивным или нет.)

Положите свои функциональные определения на файл в известном месте и используйте . (также записанный source) встроенный для включения того файла в сценарий.

$ cat ~/lib/bash/my_functions.bash
foo () {
…
$ cat ~/bin/myscript
#!/bin/bash
. ~/lib/bash/my_functions.bash
foo bar

Если Вы хотите, можно следовать за функцией автозагрузки ksh. Поместите каждое функциональное определение в файл с тем же именем как функция. Перечислите каталоги, содержащие функциональные определения в FPATH переменная (разделенный от двоеточия список каталогов). Вот грубое приближение ksh's autoload который на самом деле сразу загружает функцию вместо по запросу:

autoload () {
  set -- "$(set +f; IFS=:;
            for d in $FPATH; do
              if [ -r "$d/$1" ]; then echo -E "$d/$1"; break; fi;
            done)"
  [[ -n $1 ]] && . "$1"
}
8
27.01.2020, 19:53
  • 1
    +1 для автозагрузки, хотя я рекомендую использовать тех, которые идут с ударом. Последний поддерживает ленивую загрузку. –  Starfish 29.01.2015, 07:30

У вас Нужно функция? Если нет, рассмотрите возможность вытягивания логики в отдельный, автономный скрипт Bash в вашем пути $ PATH . Например, у меня было это в моем ~ / .bashrc :

# echo public IP address
alias wanip='dig +short myip.opendns.com @resolver1.opendns.com'

~ / bin в моем $ PATH , поэтому я создал ~ / bin / Wanip со следующим содержимым:

#!/bin/bash

# echo public IP address
dig +short myip.opendns.com @resolver1.opendns.com

и RAN CHMOD 0755 ~ / BIN / WANIP , чтобы сделать его исполняемым. Теперь я могу выполнить Wanip из других сценариев.

Мне нравится иметь Wanip в автономном сценарии Bash. Это напоминает мне, что я хочу, чтобы эта логика, как правило, доступна (кроме как раз в моей текущей интерактивной сессии Bash). Сценарий красиво инкапсулирует логику и документацию на то же самое.

0
27.01.2020, 19:53

Теги

Похожие вопросы