Як я можу запустити функцію зі скрипту в командному рядку?


119

У мене є сценарій, який має деякі функції.

Чи можу я запустити одну з функцій безпосередньо з командного рядка?

Щось на зразок цього?

myScript.sh func()

Відповіді:


66

Якщо скрипт визначає лише функції, а нічого іншого не робить, ви можете спочатку виконати скрипт у контексті поточної оболонки за допомогою команди sourceабо, .а потім просто викликати функцію. Див. Для help sourceотримання додаткової інформації.


1
Єдина проблема цього методу полягає в тому, що якщо ви використовуєте exitу своїй функції, він закриє термінал після виконання функції. Чи є спосіб обходити це? @SvenMarnach
користувач1527227

@ user1527227: Перейдіть із наступною відповіддю в такому випадку, якщо у вас є контроль над сценарієм оболонки. Якщо ви цього не зробите, ви можете зателефонувати спочатку в інтерактивну підкатегорію (просто введіть bash), і exitбуде лише припинити її, але не ваш термінал.
Свен Марнах

238

Ну а поки інші відповіді правильні - ви, звичайно, можете зробити щось інше: якщо у вас є доступ до скрипту bash, ви можете змінити його та просто помістити в кінці спеціальний параметр "$@"- який розшириться на аргументи командного рядка ви вказуєте, і оскільки це "поодинці", оболонка спробує назвати їх дослівно; і тут ви можете вказати ім'я функції як перший аргумент. Приклад:

$ cat test.sh
testA() {
  echo "TEST A $1";
}

testB() {
  echo "TEST B $2";
}

"$@"


$ bash test.sh
$ bash test.sh testA
TEST A 
$ bash test.sh testA arg1 arg2
TEST A arg1
$ bash test.sh testB arg1 arg2
TEST B arg2

Для польської мови спочатку можна переконатися, що команда існує та є функцією:

# Check if the function exists (bash specific)
if declare -f "$1" > /dev/null
then
  # call arguments verbatim
  "$@"
else
  # Show a helpful error
  echo "'$1' is not a known function name" >&2
  exit 1
fi

16
Використовують "$@"у більшості випадків. $@в деяких випадках не є безпечним.
фумія

1
Як запустити більше функції? наприклад, чи можна бігати bash test.sh testA testB?
Джефф Панг

Це також потрібно загорнути в [ ! -z "$1" ]іншому випадку, джерело підніме інше твердження в деяких версіях bash
JackLeo

Я шукав цю магічну змінну "$ @" поблизу і далеко для використання будь-якої функції, яка викликається у файлі, дякую @sdaau!
Джастін Хаммонд

36

Наступна команда спочатку реєструє функцію в контексті, а потім викликає її:

. ./myScript.sh && function_name

1
Ви також можете просто використовувати джерело. Як в - джерело myScript.sh && function_name
ukradeni_leves

17

Коротко, ні.

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

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


1
Я думаю, що цьому слід надати більше ваги як відповідної відповіді. Я намагався зробити щось подібне до того, чого хоче ОП, але сценарій оболонок просто не розроблений для "чистого розрізу, розробки OOP" (IMHO).
Дан L

4

Використання case

#!/bin/bash

fun1 () {
    echo "run function1"
    [[ "$@" ]] && echo "options: $@"
}

fun2 () {
    echo "run function2"
    [[ "$@" ]] && echo "options: $@"
}

case $1 in
    fun1) "$@"; exit;;
    fun2) "$@"; exit;;
esac

fun1
fun2

Цей скрипт буде виконувати функції fun1 та fun2, але якщо ви запускаєте його з параметрами fun1 або fun2, він запускає лише задану функцію з аргументами (якщо вона надана) та вихід. Використання

$ ./test 
run function1
run function2

$ ./test fun2 a b c
run function2
options: a b c

1

Редагувати: ПОПЕРЕДЖЕННЯ - здається, це працює не у всіх випадках, але добре працює у багатьох публічних сценаріях.

Якщо у вас є bash-скрипт під назвою "control", а всередині нього у вас є функція під назвою "build":

function build() { 
  ... 
}

Тоді ви можете назвати це так (з каталогу, де він знаходиться):

./control build

Якщо це всередині іншої папки, це зробить це:

another_folder/control build

Якщо ваш файл називається "control.sh", це відповідно зробить функцію, яку можна викликати так:

./control.sh build

1
Це не працювало в інтерактивній оболонці для мене. Але це спрацювало:. ./control.sh && build
saulius2

1

У мене є ситуація, коли мені потрібна функція з bash script, яка не повинна виконуватися раніше (наприклад, за допомогою source), і проблема @$полягає в тому, що myScript.sh потім виконується двічі, здається ... Тому я придумав ідею щоб вийти з функції sed:

sed -n "/^func ()/,/^}/p" myScript.sh

І щоб виконати його в той час, коли мені це потрібно, я вкладаю його у файл і використовую source:

sed -n "/^func ()/,/^}/p" myScript.sh > func.sh; source func.sh; rm func.sh


0

ви можете викликати функцію з аргументу командного рядка, як показано нижче

function irfan() {
echo "Irfan khan"
date
hostname
}
function config() {
ifconfig
echo "hey"
}
$1

як тільки ви закінчите функцію, покладіть $ 1 на прийняття аргументу, скажімо, вищезгаданий код зберігається у fun.sh для запуску функції ./fun.sh irfan & ./fun.sh config


0

Вирішена посада, але я хотів би згадати своє вподобане рішення. А саме, визначте загальний сценарій з одним вкладишем eval_func.sh:

#!/bin/bash
source $1 && shift && "@a"

Потім зателефонуйте до будь-якої функції в будь-якому сценарії через:

./eval_func.sh <any script> <any function> <any args>...

Проблема, з якою я зіткнувся з прийнятим рішенням, полягає в тому, що при пошуку мого сценарію, що містить функцію, в іншому сценарії, аргументи останнього будуть оцінені першим, що спричинить помилку.

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