ฉันสามารถเรียกใช้ฟังก์ชันของเชลล์สคริปต์จากเชลล์สคริปต์อื่นได้หรือไม่


87

ฉันมี 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`


}

first.sh

second.sh cricket football

func1 love horror
func2 ball mystery

ฉันจะบรรลุได้อย่างไร?



3
v=$(echo $1)ซ้ำซ้อนอย่างสมบูรณ์ fun2=$1เขียนเพียง ข้อแตกต่างเพียงอย่างเดียวคือ$()(หรือ backticks) จะลบบรรทัดใหม่ต่อท้าย
William Pursell

1
เนื่องจากไม่มีอะไรพิเศษเกี่ยวกับการเรียกใช้ฟังก์ชันจากเชลล์สคริปต์เมื่อเทียบกับบรรทัดคำสั่งคำถามนี้สามารถลดลงเป็น "จะเรียกฟังก์ชันทุบตีได้อย่างไร"
Tom Russell

คำตอบ:


146

ปรับโครงสร้าง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

44

คุณไม่สามารถเรียกใช้ฟังก์ชันในเชลล์สคริปต์อื่นได้โดยตรง

คุณสามารถย้ายข้อกำหนดฟังก์ชันของคุณไปไว้ในไฟล์แยกต่างหากจากนั้นโหลดลงในสคริปต์ของคุณโดยใช้.คำสั่งดังนี้:

. /path/to/functions.sh

สิ่งนี้จะตีความfunctions.shราวกับว่ามีเนื้อหาอยู่ในไฟล์ของคุณ ณ จุดนี้ นี่เป็นกลไกทั่วไปสำหรับการนำไลบรารีที่แบ่งใช้ของฟังก์ชันเชลล์ไปใช้


3
คำตอบนี้ไม่เหมือนกับคำตอบที่ได้รับการยอมรับเนื่องจาก.เป็นนามแฝงสำหรับsource?
ajsharma

10
ฉันตอบก่อนดังนั้นในทางเทคนิคคำตอบที่ยอมรับก็เหมือนกับคำตอบนี้ :) นอกจากนี้ในขณะที่sourceเป็นนามแฝงสำหรับ.เชลล์จำนวนมาก แต่ก็ไม่ได้เป็นเช่นนั้นเสมอไป ตัวอย่างเช่นdashแพ็กเกจบน Debian ซึ่งมีให้/bin/shไม่มีsourceคำสั่ง
larsks

sourceคำสั่งไม่ทำงานใน Ubuntu @ajsharma ข้อมูลอ้างอิง: ไม่พบคำสั่ง source ใน sh shell
rajeshmag

แปลกมากที่ความคิดเห็นนี้ไม่ได้รับการโหวตให้สูงที่สุด? นี่คือไวยากรณ์ #! / bin / sh ที่ถูกต้องและอีกแบบจะใช้ได้เฉพาะใน bash
xddq

21

ปัญหา

คำตอบที่ยอมรับกันโดยทั่วไปจะใช้ได้เฉพาะในเงื่อนไขที่สำคัญเท่านั้น ให้ ...

/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มันสัมพันธ์กับเส้นทางการทำงานปัจจุบันไม่ใช่เส้นทางของสคริปต์ ดังนั้นวิธีแก้ปัญหาหนึ่งคือการใช้ subshell และเรียกใช้

(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

ใน file1 (chmod 750 file1) และ file2

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

และเรียกใช้. / file2 คุณจะได้รับ Fun1 จาก file1 Hello Fun1 จาก file2 สวัสดีเซอร์ไพรส์ !!! คุณเขียนทับ fun1 ใน file1 ด้วย fun1 จาก file2 ... ดังนั้นคุณต้องไม่ทำเช่นนั้น

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

มันบันทึกคำจำกัดความก่อนหน้าของคุณสำหรับ fun1 และเรียกคืนโดยไม่จำเป็นต้องนำเข้าชื่อก่อนหน้า ทุกครั้งที่คุณนำเข้าฟังก์ชันจากไฟล์อื่นคุณอาจจำสองด้าน:

  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

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.