Tôi có thể gọi một hàm của shell script từ một shell script khác không?


86

Tôi có 2 kịch bản shell.

Tập lệnh shell thứ hai chứa các hàm sau second.sh

func1 
func2

First.sh sẽ gọi tập lệnh shell thứ hai với một số tham số và sẽ gọi func1 và func2 với một số tham số khác cụ thể cho hàm đó.

Đây là ví dụ về những gì tôi đang nói về

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

Làm thế nào tôi có thể đạt được nó?



3
v=$(echo $1)là hoàn toàn dư thừa. Chỉ cần viết fun2=$1. Sự khác biệt duy nhất là $()(hoặc dấu gạch ngược) sẽ loại bỏ các dòng mới ở cuối.
William Pursell

1
Vì không có gì đặc biệt khi gọi một hàm từ tập lệnh shell thay vì dòng lệnh, câu hỏi này có thể được rút gọn thành "Làm thế nào để gọi một hàm bash?"
Tom Russell,

Câu trả lời:


145

Cấu trúc lại second.shtập lệnh của bạn như sau:

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

Và sau đó gọi các hàm này từ script first.shnhư sau:

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

ĐẦU RA:

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

12
Để tránh các tác dụng phụ không chủ ý, hãy lưu ý rằng sourcelệnh sẽ thực sự chạy tập lệnh được truyền dưới dạng đối số.
dvlcube

43

Bạn không thể gọi trực tiếp một hàm trong tập lệnh shell khác.

Bạn có thể di chuyển các định nghĩa hàm của mình vào một tệp riêng và sau đó tải chúng vào tập lệnh của bạn bằng .lệnh, như sau:

. /path/to/functions.sh

Điều này sẽ diễn giải functions.shnhư thể nội dung của nó thực sự có trong tệp của bạn tại thời điểm này. Đây là một cơ chế phổ biến để triển khai các thư viện dùng chung của các hàm shell.


3
Đây không phải là câu trả lời được chấp nhận, vì .nó là một bí danh cho source?
ajsharma

9
Vâng, tôi đã trả lời trước, vì vậy về mặt kỹ thuật, câu trả lời được chấp nhận giống như câu này :). Ngoài ra, mặc dù sourcelà một bí danh cho .nhiều shell, nhưng điều đó không phải lúc nào cũng đúng. Ví dụ, dashgói trên Debian, cung cấp /bin/sh, không có sourcelệnh.
larsks

sourcelệnh không hoạt động trong Ubuntu @ajsharma. Tham khảo: lệnh nguồn không tìm thấy trong vỏ sh
rajeshmag

kỳ lạ đến mức nhận xét này không được ủng hộ là cao nhất? Đây là cú pháp #! / Bin / sh chính xác và cú pháp kia sẽ chỉ hoạt động trong bash.
xddq

20

Vấn đề

Câu trả lời được chấp nhận rõ ràng chỉ hoạt động trong điều kiện quan trọng. Được...

/foo/bar/first.sh:

function func1 {  
   echo "Hello $1"
}

/foo/bar/second.sh:

#!/bin/bash

source ./first.sh
func1 World

điều này chỉ hoạt động nếu first.shđược thực thi từ trong cùng một thư mục first.shcó vị trí. I E. nếu đường làm việc hiện tại của shell là /foo, cố gắng chạy lệnh

cd /foo
./bar/second.sh

lỗi in:

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

Đó là bởi vì source ./first.shđường dẫn liên quan đến đường dẫn làm việc hiện tại, không phải đường dẫn của tập lệnh. Do đó, một giải pháp có thể là sử dụng vỏ con và chạy

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

Giải pháp chung chung hơn

Được...

/foo/bar/first.sh:

function func1 {  
   echo "Hello $1"
}

/foo/bar/second.sh:

#!/bin/bash

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

func1 World

sau đó

cd /foo
./bar/second.sh

bản in

Hello World

Làm thế nào nó hoạt động

  • $0 trả về đường dẫn tương đối hoặc tuyệt đối đến tập lệnh được thực thi
  • dirname trả về đường dẫn tương đối đến thư mục, nơi tập lệnh $ 0 tồn tại
  • $( dirname "$0" )các dirname "$0"lệnh trả về đường dẫn tương đối đến thư mục của kịch bản thực hiện, sau đó được sử dụng như là đối số cho sourcelệnh
  • trong "second.sh", /first.shchỉ cần thêm tên của tập lệnh shell đã nhập
  • source tải nội dung của tệp được chỉ định vào trình bao hiện tại

0

Nếu bạn xác định

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

trong file1 (chmod 750 file1) và file2

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

và chạy ./file2 bạn sẽ nhận được Fun1 từ tệp1 Xin chào Fun1 từ tệp2 Xin chào bất ngờ !!! Bạn ghi đè fun1 trong file1 bằng fun1 từ file2 ... Vì vậy, bạn phải làm như vậy

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

nó lưu định nghĩa trước đó của bạn cho fun1 và khôi phục nó với tên trước đó xóa không cần thiết đã nhập. Mỗi khi bạn nhập các hàm từ một tệp khác, bạn có thể nhớ hai khía cạnh:

  1. bạn có thể ghi đè những cái hiện có bằng những cái tên giống nhau (nếu đó là thứ bạn muốn, bạn phải giữ chúng như được mô tả ở trên)
  2. nhập tất cả nội dung của tệp nhập (các hàm và cả biến toàn cục nữa) Hãy cẩn thận! Đó là thủ tục nguy hiểm

-5
#vi function.sh

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

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

#sh function.sh

Ở đây hàm f2sẽ gọi hàmf1

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.