Komut satırındaki bir komut dosyasından bir işlevi nasıl çalıştırabilirim?


119

Bazı işlevleri olan bir komut dosyam var.

İşlevlerden birini doğrudan komut satırından çalıştırabilir miyim?

Bunun gibi bir şey mi?

myScript.sh func()

Yanıtlar:


66

Komut dosyası yalnızca işlevleri tanımlıyorsa ve başka hiçbir şey yapmıyorsa, önce sourceveya .komutunu kullanarak betiği geçerli kabuğun bağlamı içinde çalıştırabilir ve ardından işlevi çağırabilirsiniz. Daha help sourcefazla bilgi için bakın .


1
Bu yöntemle ilgili tek sorun exit, işlevinizde kullanırsanız , işlev çalıştırıldıktan sonra terminali kapatacak olmasıdır. Bunun etrafında herhangi bir yol var mı? @SvenMarnach
user1527227

@ user1527227: Kabuk betiğinin kontrolüne sahip olduğunuz sürece, bu durumda bir sonraki cevaba geçin. Bunu yapmazsanız, önce etkileşimli bir alt kabuğu çağırabilirsiniz (sadece girin bash) ve exityalnızca alt kabuğu sonlandırır, terminalinizi değil.
Sven Marnach

238

Pekala, diğer cevaplar doğruyken - kesinlikle başka bir şey yapabilirsiniz: bash betiğine erişiminiz varsa, onu değiştirebilir ve basitçe "$@", komut satırının argümanlarına genişleyecek olan özel parametrenin sonuna yerleştirebilirsiniz. siz belirtirsiniz ve "yalnız" olduğu için kabuk onları kelimesi kelimesine çağırmaya çalışır; ve burada ilk bağımsız değişken olarak işlev adını belirtebilirsiniz. Misal:

$ 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

Lehçe için, önce komutun var olduğunu ve bir işlev olduğunu doğrulayabilirsiniz:

# 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
"$@"Çoğu durumda kullanın . $@bazı durumlarda güvenli değildir.
fumiyas

1
Bir işlevden daha fazlası nasıl çalıştırılır? örneğin koşabilir bash test.sh testA testBmiyim?
Jeff Pang

Bunun da sarılması gerekiyor, [ ! -z "$1" ]aksi takdirde kaynak bazı bash
sürümlerinde

Bir dosyada hangi işlev çağrılırsa kullanılsın, bu sihirli "$ @" değişkenini yakından ve uzaklarda arıyordum, teşekkür ederim @sdaau!
Justin Hammond

36

Aşağıdaki komut önce işlevi bağlamda kaydeder, sonra çağırır:

. ./myScript.sh && function_name

1
Ayrıca kaynağı da kullanabilirsiniz. İçinde olduğu gibi - kaynak myScript.sh && function_name
stolen_leaves

17

Kısaca hayır.

source( help sourceAyrıntılar için) ile komut dosyasındaki tüm işlevleri ortamınıza aktarabilirsiniz , bu da onları aramanıza olanak tanır. Bu aynı zamanda betiği çalıştırma etkisine sahiptir, bu yüzden dikkatli olun.

Bir işlevi bir kabuk komut dosyasından paylaşılan bir kitaplık gibi çağırmanın bir yolu yoktur.


1
Buna uygun bir cevap olarak daha fazla ağırlık verilmesi gerektiğini düşünüyorum. OP'nin istediğine benzer bir şey yapmaya çalıştım, ancak kabuk komut dosyası basitçe "temiz kesim, OOP geliştirme" (IMHO) için tasarlanmadı.
Dan L

4

kullanma 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

Bu komut dosyası fun1 ve fun2 işlevlerini çalıştıracaktır, ancak onu fun1 veya fun2 seçeneğiyle başlatırsanız, yalnızca belirli bir işlevi bağımsız değişkenlerle (varsa) çalıştırır ve çıkar. kullanım

$ ./test 
run function1
run function2

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

1

Düzenleme: UYARI - bu her durumda işe yaramıyor gibi görünüyor, ancak birçok genel komut dosyasında iyi çalışıyor.

"Kontrol" adında bir bash betiğiniz varsa ve içinde "inşa" adında bir işleviniz varsa:

function build() { 
  ... 
}

O zaman bunu şu şekilde çağırabilirsiniz (bulunduğu dizinden):

./control build

Başka bir klasörün içindeyse, bu onu yapar:

another_folder/control build

Dosyanız "control.sh" olarak adlandırılırsa, bu da işlevi şu şekilde çağrılabilir hale getirir:

./control.sh build

1
Bu benim için etkileşimli kabukta işe yaramadı. Ama bu işe yaradı:. ./control.sh && build
saulius2

1

Daha önce çalıştırılmaması gereken (örneğin tarafından source) bash betiğinden bir işleve ihtiyaç duyduğum bir durumum var ve sorun @$şu ki myScript.sh daha sonra iki kez çalıştırılıyor, öyle görünüyor ... işlevi sed ile çıkarmak için:

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

Ve ihtiyacım olduğu anda yürütmek için bir dosyaya koyup şunu kullanıyorum source:

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


0

aşağıdaki gibi komut satırı argümanından işlevi çağırabilirsiniz

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

işlev bittiğinde argümanı kabul etmek için $ 1 koyun, diyelim ki yukarıdaki kod işlevi çalıştırmak için fun.sh içine kaydedildi ./fun.sh irfan & ./fun.sh config


0

Çözülmüş gönderi ancak tercih ettiğim çözümden bahsetmek istiyorum. Yani, genel bir tek satırlık komut dosyası tanımlayın eval_func.sh:

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

Ardından herhangi bir komut dosyası içindeki herhangi bir işlevi şu yolla çağırın:

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

Kabul edilen çözümle karşılaştığım bir sorun, işlev içeren komut dosyamı başka bir komut dosyası içinden kaynak alırken, ikincisinin argümanlarının birincisi tarafından değerlendirilerek bir hataya neden olmasıydı.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.