Як визначити функцію Bash, яку можуть використовувати різні сценарії


13

Я визначив bashфункцію у своєму ~/.bashrcфайлі. Це дозволяє мені використовувати його в терміналах оболонки. Однак, схоже, це не існує, коли я закликаю його зсередини сценарію.

Як я можу визначити bashфункцію, яка також використовується сценаріями?


Але мій .bash_profile в основному читає файл .basrc, тому я б очікував, що результат буде однаковим, незалежно від того, використовую я оболонку для входу або не вхід.
Onturenio

Ви використовуєте /bin/shв лінії shebang?
Кевін

Відповіді:


9

~/.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. Це набагато портативніше і не покладається на те, що ваше середовище створене певним чином.


чому б просто не оголосити функцію на зразок function myFunction { ... }in, ~/.bash_profileі вам добре піти?
амфібій

Якщо я правильно зрозумів вашу відповідь (щодо пошуку файлу з функцією), це означатиме, що мені доведеться явно шукати файл у кожному сценарії, що дуже дратує. Це не набагато складніше, ніж просто копіювання самої функції у кожному сценарії. Я б врятував деякі рядки, звичайно, але це все. Однак exportрішення, здається, працює належним чином. Спасибі.
Onturenio

@foampile, це саме те, що я робив і не працює, коли викликає функцію зі сценарію.
Onturenio

1
@Onturenio: другий метод @ Кріс вниз запропонував дійсно краще: 1) Коли хто - то прочитало сценарій, вони знають , що вона потребує в деякій fooфункції від деяких file2) Ви можете краще контролювати зміст цього fileніж переконайтеся , що викликає оболонка не змінилася fooперед тим, як викликати ваш сценарій. Ви можете додати перевірки безпеки, fileщоб переконатися, що це, наприклад, не працює. (не просто, але можливо). (ну, ви також можете зробити ці перевірки визначеної функції foo ... але ви отримаєте мій дрейф ^^ Я думаю, що метод 2 чистіший.) 3) fileбуде містити лише те, що потрібно, а не більше.
Олів'є Дулак

8

.bashrcчитається лише інтерактивними оболонками. (Насправді, це надмірне спрощення: bash є химерним у цьому відношенні. Bash не читає, .bashrcчи це оболонка для входу, інтерактивна чи ні. І є виняток навіть виняток: якщо батьківський процес bash є, rshdабо sshdbash читає .bashrc, будь то інтерактивна чи ні.)

Помістіть визначення своїх функцій у файл у відомому місці та використовуйте .(також написаний source) вбудований файл, щоб включити цей файл у сценарій.

$ cat ~/lib/bash/my_functions.bash
foo () {

$ cat ~/bin/myscript
#!/bin/bash
. ~/lib/bash/my_functions.bash
foo bar

Якщо ви хочете, ви можете скористатися функцією автозавантаження ksh. Покладіть кожне визначення функції у файл з тим же ім'ям, що і функція. Перерахуйте каталоги, що містять визначення функцій у FPATHзмінній (список розділених двокрапкою точок). Ось грубе наближення ksh, 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"
}

+1 для автоматичного завантаження, хоча я рекомендую використовувати ті, що постачаються з bash. Останній підтримує ледачий навантаження.
Морська зірка

0

Вам потрібна функція? Якщо ні, подумайте про виведення логіки в окремий, автономний сценарій 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

І побіг, chmod 0755 ~/bin/wanipщоб зробити його виконуваним. Тепер я можу виконати wanipз інших сценаріїв.

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

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.