Чи можу я викликати функцію сценарію оболонки з іншого сценарію оболонки?


86

У мене є 2 сценарії оболонки.

Другий сценарій оболонки містить наступні функції second.sh

func1 
func2

First.sh викличе другий скрипт оболонки з деякими параметрами, а func1 та func2 з деякими іншими параметрами, специфічними для цієї функції.

Ось приклад того, про що я говорю

друге.ш

val1=`echo $1`
val2=`echo $2`

function func1 {

fun=`echo $1`
book=`echo $2`

}

function func2 {

fun2=`echo $1`
book2=`echo $2`


}

спочатку.ш

second.sh cricket football

func1 love horror
func2 ball mystery

Як я можу цього досягти?



3
v=$(echo $1)є повністю зайвим. Просто напишіть fun2=$1. Єдина відмінність полягає в тому, що $()(або зворотні позначки) видалять кінцеві нові рядки.
Вільям Перселл,

1
Оскільки у виклику функції зі сценарію оболонки немає нічого особливого, на відміну від командного рядка, це питання можна звести до "Як викликати функцію bash?"
Том Рассел

Відповіді:


145

Переформатуйте ваш second.shсценарій так:

function func1 {
   fun=$1
   book=$2
   printf "fun=%s,book=%s\n" "${fun}" "${book}"
}

function func2 {
   fun2=$1
   book2=$2
   printf "fun2=%s,book2=%s\n" "${fun2}" "${book2}"
}

А потім викличте ці функції зі сценарію first.shтак:

source ./second.sh
func1 love horror
func2 ball mystery

ВИХІД:

fun=love,book=horror
fun2=ball,book2=mystery

12
Щоб уникнути ненавмисних побічних ефектів, пам’ятайте, що sourceкоманда фактично запустить сценарій, переданий як аргумент.
dvlcube

43

Ви не можете безпосередньо викликати функцію в іншому сценарії оболонки.

Ви можете перемістити визначення функцій в окремий файл, а потім завантажити їх у свій скрипт за допомогою .команди, наприклад:

. /path/to/functions.sh

Це спричинить functions.shтак, ніби його вміст справді присутній у вашому файлі. Це загальний механізм реалізації спільних бібліотек функцій оболонки.


3
Хіба це не те саме, що прийнята відповідь, оскільки .це псевдонім source?
ajsharma

9
Ну, я відповів першим, тож технічно прийнята відповідь така ж, як і ця :). Крім того, хоча sourceпсевдонім для .багатьох оболонок, це не завжди так. Наприклад, dashпакет на Debian, який надає /bin/sh, не має sourceкоманди.
larsks

sourceкоманда не працювала в Ubuntu @ajsharma. Довідково: команду джерела не знайдено в оболонці sh
rajeshmag

настільки дивно, що цей коментар не проголосували як найвищий? Це правильний синтаксис #! / Bin / sh, а інший працюватиме лише в bash.
xddq

20

Проблема

Точно прийнята відповідь працює лише за важливої ​​умови. Враховуючи ...

/foo/bar/first.sh:

function func1 {  
   echo "Hello $1"
}

і

/foo/bar/second.sh:

#!/bin/bash

source ./first.sh
func1 World

це працює лише в тому випадку, якщо first.shвиконується з того самого каталогу, де first.shзнаходиться. Тобто. якщо поточний робочий шлях оболонки - /fooспроба запустити команду

cd /foo
./bar/second.sh

помилка друку:

/foo/bar/second.sh: line 4: func1: command not found

Це тому, що source ./first.shвідносно поточного робочого шляху, а не шляху сценарію. Отже, одним із рішень може бути використання під оболонки та запуск

(cd /foo/bar; ./second.sh)

Більш загальне рішення

Враховуючи ...

/foo/bar/first.sh:

function func1 {  
   echo "Hello $1"
}

і

/foo/bar/second.sh:

#!/bin/bash

source $(dirname "$0")/first.sh

func1 World

тоді

cd /foo
./bar/second.sh

відбитки

Hello World

Як це працює

  • $0 повертає відносний або абсолютний шлях до виконаного сценарію
  • dirname повертає відносний шлях до каталогу, де існує скрипт $ 0
  • $( dirname "$0" )dirname "$0"команда повертає відносний шлях до директорії виконуваного скрипта, який потім використовується в якості аргументу для sourceкоманди
  • у "second.sh" /first.shпросто додає ім'я імпортованого сценарію оболонки
  • source завантажує вміст зазначеного файлу в поточну оболонку

0

Якщо ви визначите

    #!/bin/bash
        fun1(){
          echo "Fun1 from file1 $1"
        }
fun1 Hello
. file2 
fun1 Hello
exit 0

у файлі1 (chmod 750 файл1) та файлі2

   fun1(){
      echo "Fun1 from file2 $1"
    }
    fun2(){
      echo "Fun1 from file1 $1"
    }

і запустіть ./file2 ви отримаєте Fun1 з файлу1 Привіт Fun1 з файлу2 Привіт сюрприз !!! Ви замінюєте fun1 у файлі1 на fun1 з файлу2 ... Щоб цього не робити, ви повинні

declare -f pr_fun1=$fun1
. file2
unset -f fun1
fun1=$pr_fun1
unset -f pr_fun1
fun1 Hello

це зберегти попереднє визначення для розваги1 та відновити його з попереднім іменем, видаливши непотрібне імпортоване. Щоразу, коли ви імпортуєте функції з іншого файлу, ви можете пам’ятати два аспекти:

  1. Ви можете переписати існуючі з однаковими іменами (якщо це те, що вам потрібно, ви повинні зберегти їх, як описано вище)
  2. імпортувати весь вміст файлу імпорту (функції та глобальні змінні теж) Будьте обережні! Це небезпечна процедура

-5
#vi function.sh

#!/bin/bash
f1() {
    echo "Hello $name"
}

f2() {
    echo "Enter your name: "
    read name
    f1
}
f2

#sh function.sh

Тут функція f2викличе функціюf1

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