Başka bir kabuk betiğinden bir kabuk betiğinin işlevini çağırabilir miyim?


87

2 kabuk komut dosyam var.

İkinci kabuk betiği aşağıdaki işlevleri içerir second.sh

func1 
func2

First.sh, ikinci kabuk betiğini bazı parametrelerle çağırır ve bu işleve özgü diğer bazı parametrelerle func1 ve func2'yi çağırır.

İşte bahsettiğim şeyin bir örneği

second.sh

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

function func1 {

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

}

function func2 {

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


}

first.sh

second.sh cricket football

func1 love horror
func2 ball mystery

Bunu nasıl başarabilirim?



3
v=$(echo $1)tamamen gereksizdir. Sadece yazın fun2=$1. Tek fark, $()(veya ters işaretlerin) sondaki yeni satırları kaldırmasıdır.
William Pursell

1
Komut satırının aksine bir kabuk betiğinden bir işlevi çağırmanın özel bir yanı olmadığından, bu soru "Bir bash işlevi nasıl çağrılır?"
Tom Russell

Yanıtlar:


146

second.shKomut dosyanızı şu şekilde yeniden düzenleyin :

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}"
}

Ve sonra bu işlevleri komut dosyasından şu şekilde çağırın first.sh:

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

ÇIKTI:

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

12
İstenmeyen yan etkilerden kaçınmak için, sourcekomutun aslında argüman olarak aktarılan betiği çalıştıracağına dikkat edin .
dvlcube

44

Başka bir kabuk betiğindeki bir işlevi doğrudan çağıramazsınız.

İşlev tanımlarınızı ayrı bir dosyaya taşıyabilir ve ardından aşağıdaki .gibi komutu kullanarak bunları betiğinize yükleyebilirsiniz :

. /path/to/functions.sh

Bu, functions.shiçeriğinin bu noktada dosyanızda gerçekten mevcut olduğu şeklinde yorumlanacaktır . Bu, paylaşılan kabuk işlev kitaplıklarını uygulamak için yaygın bir mekanizmadır.


3
Bunun .takma adı olduğu için kabul edilen cevapla aynı değil sourcemi?
ajsharma

10
Önce ben cevapladım, teknik olarak kabul edilen cevap bununla aynı :). Ayrıca, birçok mermide sourcetakma ad olsa da ., bu her zaman böyle değildir. Örneğin dashDebian üzerindeki paketin /bin/shbir sourcekomutu yoktur.
larsks

sourcekomut Ubuntu @ajsharma'da çalışmadı. Referans: kaynak komutu sh kabuğunda bulunamadı
rajeshmag

bu yorumun en yüksek olarak oylanmaması o kadar tuhaf? Bu doğru #! / Bin / sh sözdizimidir ve diğeri yalnızca bash'da çalışacaktır.
xddq

21

Sorun

Geçerli olarak kabul edilen cevap, yalnızca önemli koşullar altında işe yarar. Verilen ...

/foo/bar/first.sh:

function func1 {  
   echo "Hello $1"
}

ve

/foo/bar/second.sh:

#!/bin/bash

source ./first.sh
func1 World

bu, yalnızca , bulunduğu first.shdizinle aynı dizin içinden yürütüldüğünde çalışır first.sh. Yani. Kabuğun mevcut çalışma yolu ise /foo, komutu çalıştırma girişimi

cd /foo
./bar/second.sh

hata yazdırır:

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

Bunun nedeni source ./first.sh, komut dosyasının yoluna değil, geçerli çalışma yoluna göreli olmasıdır. Bu nedenle bir çözüm alt kabuğu kullanmak ve çalıştırmak olabilir

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

Daha genel çözüm

Verilen ...

/foo/bar/first.sh:

function func1 {  
   echo "Hello $1"
}

ve

/foo/bar/second.sh:

#!/bin/bash

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

func1 World

sonra

cd /foo
./bar/second.sh

baskılar

Hello World

Nasıl çalışır

  • $0 çalıştırılan betiğe göreli veya mutlak yolu döndürür
  • dirname $ 0 komut dosyasının mevcut olduğu dizine göreceli yolu döndürür
  • $( dirname "$0" )dirname "$0"Komut daha sonra bağımsız değişkeni olarak kullanılır yürütülen komut, bir dizinine göre yolunu döndürür sourcekomutu
  • "second.sh" içinde, /first.shsadece içe aktarılan kabuk betiğinin adını ekler
  • source belirtilen dosyanın içeriğini mevcut kabuğa yükler

0

Eğer tanımlarsan

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

dosya1 (chmod 750 dosya1) ve dosya2'de

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

ve ./file2 komutunu çalıştırın. Dosya1'den Fun1'i alacaksınız. Hello Fun1, file2'den Merhaba Sürpriz !!! Dosya1'deki fun1'in üzerine dosya2'deki fun1 ile yazarsınız ... Bunu yapmamak için yapmanız gerekir

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

önceki tanımınızı fun1 için kaydeder ve onu önceki adı silerek, gerekmeyen içe aktarılan tanımla geri yükler. Başka bir dosyadan işlevleri her içe aktardığınızda iki yönü hatırlayabilirsiniz:

  1. aynı isimlerle mevcut olanların üzerine yazabilirsiniz (eğer istediğiniz şeyi yukarıda açıklandığı gibi korumalısınız)
  2. içe aktarılan dosyanın tüm içeriğini içe aktarın (işlevler ve global değişkenler de) Dikkatli olun! Bu tehlikeli bir prosedür

-5
#vi function.sh

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

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

#sh function.sh

Burada işlev işlevi f2çağıracakf1

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.