การคืนค่าจากฟังก์ชัน bash


10

ฉันมีฟังก์ชั่นซึ่งจะคืนค่า 1 หากจำนวนนั้นเป็นตัวเลขสิบหลักที่ถูกต้อง:

valNum()
{
    flag=1
    if [[ $1 != [1-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9] ]]; then
        echo "Invalid Number"
        flag=0
    fi
    return $flag
}

มันกำลังถูกเรียกโดย:

if [[ $(valNum $num) -eq 1 ]]; then
      #do something
fi

ฟังก์ชั่นทำงานได้ดีถ้าตัวเลขนั้นถูกต้อง แต่มีการแสดงข้อผิดพลาดทางไวยากรณ์หากใส่หมายเลขที่ไม่ถูกต้อง

คำตอบ:


14

คำตอบของ @ choroba ถูกต้อง แต่ตัวอย่างนี้อาจชัดเจน:

valNum $num
valNumResult=$? # '$?' is the return value of the previous command
if [[ $valNumResult -eq 1 ]]
then
  : # do something
fi

ตัวอย่างนี้ใช้เวลานานกว่าเล็กน้อย (การตั้งค่า$valNumResultจากนั้นสอบถามค่านั้น) แต่จะอธิบายสิ่งที่เกิดขึ้นอย่างชัดเจนยิ่งขึ้น: ซึ่งvalNum()จะส่งกลับค่าและค่านั้นสามารถสอบถามและทดสอบได้

PS กรุณาทำด้วยตัวเองชอบและกลับ0สำหรับและไม่ใช่ศูนย์true falseด้วยวิธีนี้คุณสามารถใช้ค่าส่งคืนเพื่อระบุ "สาเหตุที่เราล้มเหลว" ในกรณีความล้มเหลว


8

ฟังก์ชันใน bash สามารถส่งคืนรหัสทางออกได้เท่านั้น การทดแทนคำสั่งตรงกันข้ามใช้เพื่อรับเอาต์พุตมาตรฐานของคำสั่งหรือฟังก์ชัน ดังนั้นในการตรวจสอบการตั้งค่าสถานะที่ส่งคืนคุณไม่จำเป็นต้องทำการทดแทน:

if valNum "$num" ; then
    # ...
fi

แต่เพื่อให้สามารถใช้งานได้คุณควรส่งคืน 0 ถ้าหมายเลขนั้นถูกต้องและ 1 ถ้าไม่ (รหัสทางออก 0 หมายถึงไม่มีข้อผิดพลาด)


ฉันไม่เข้าใจ ในตัวอย่าง 24.7 ในtldp.org/LDP/abs/html/complexfunct.htmlฟังก์ชันกำลังส่งคืนค่าสูงสุดไม่ใช่รหัสออก แม้ว่าข้อเสนอแนะของคุณจะทำงาน แต่ฉันไม่สามารถเข้าใจว่าทำไมมันถึงทำงาน
user2179293

1
เนื่องจากการทดสอบของคุณคือการค้นหาว่าอินพุตเป็นจำนวนเต็ม 10 หลักที่ถูกต้องหรือไม่เช่นจริงหรือเท็จฟังก์ชันจะส่งคืนตัวอย่าง 0 หรือ 1 ตัวอย่างของ choroba นั้นใช้ได้เพราะif valnum "$num"เทียบเท่ากับif valnum "$num" = 0"ถ้าเป็นจริง" กฎพื้นฐานของหัวแม่มือในการเขียนสคริปต์ sh คือ 0 = จริง / สำเร็จไม่ใช่ศูนย์ = เท็จ / ข้อผิดพลาด
cas

2
BTW ว่า "คู่มือการใช้สคริปต์การทุบตีขั้นสูง" ไม่ใช่คำแนะนำที่ดีมาก - มันผิดเกี่ยวกับหลายสิ่งหลายอย่างและกระตุ้นให้เกิดการปฏิบัติสคริปต์ที่ไม่ดี Bash คำถามที่พบบ่อยที่mywiki.wooledge.org/BashFAQเป็นทรัพยากรที่ดีกว่ามาก
cas


ฟังก์ชั่นของคุณล้มเหลวเพราะมันเป็นเสียงสะท้อนของสตริง "หมายเลขไม่ถูกต้อง" และจากนั้นคุณทำการเปรียบเทียบตัวเลขระหว่างสตริงนั้นและหมายเลข 1 ด้วยif [[ $(valNum $num) -eq 1 ]]
cas

5

คุณไม่สามารถส่งคืนผลลัพธ์โดยพลการจากฟังก์ชันเชลล์ คุณสามารถส่งคืนรหัสสถานะซึ่งเป็นจำนวนเต็มระหว่าง 0 ถึง 255 เท่านั้น (ในขณะที่คุณสามารถส่งผ่านค่าที่returnมากกว่าได้มันจะถูกตัดทอนโมดูโล 256) ค่าต้องเป็น 0 เพื่อระบุความสำเร็จและค่าอื่นเพื่อระบุความล้มเหลว ตามแบบแผนคุณควรติดกับรหัสข้อผิดพลาดระหว่าง 1 ถึง 125 เนื่องจากค่าที่สูงกว่ามีความหมายพิเศษ (คำสั่งภายนอกที่ไม่ดีสำหรับ 126 และ 127 ถูกฆ่าโดยสัญญาณสำหรับค่าที่สูงกว่า)

เนื่องจากคุณส่งคืนผลลัพธ์ใช่หรือไม่ที่นี่รหัสสถานะจึงเหมาะสม เนื่องจากflagดูเหมือนจะบ่งบอกถึงความสำเร็จหรือความล้มเหลวคุณควรใช้ค่าปกติที่ 0 เพื่อความสำเร็จและ 1 สำหรับความล้มเหลว (ตรงกันข้ามกับสิ่งที่คุณเขียน) จากนั้นคุณสามารถใช้ฟังก์ชันของคุณโดยตรงในคำสั่ง if

valNum ()
{
  local flag=0
  if [[ $1 != [1-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9] ]]; then
    echo 1>&2 "Invalid Number"
    flag=1
  fi
  return $flag
}
if valNum "$num"; then
  #do something
fi

หากคุณต้องการแยกแยะระหว่างรหัสความล้มเหลวให้เรียกใช้ฟังก์ชันโดยตรง $?ทันทีหลังจากที่ได้กลับรหัสความล้มเหลวที่มีอยู่ใน จากนั้นคุณสามารถตรวจสอบด้วยคำสั่ง case:

valNum "$num"
case $? in 

หากคุณต้องการใช้รหัสสถานะในภายหลังให้บันทึกลงในตัวแปรอื่นก่อนที่จะ$?ถูกเขียนทับโดยคำสั่งถัดไป

valNum "$num"
valNum_status=$?

สิ่งที่คุณเขียนไม่ได้ทำงานเพราะเปลี่ยนตัวคำสั่งขยายการส่งออกของฟังก์ชั่นซึ่งในรหัสของคุณเป็นทั้งข้อผิดพลาดหรือเปล่าไม่เคย$(…)1

หากคุณต้องการส่งผ่านข้อมูลมากกว่ารหัสสถานะที่อนุญาตให้ใช้ฟังก์ชันเชลล์คุณมีความเป็นไปได้สองประการ:

  • พิมพ์ข้อความบนเอาต์พุตมาตรฐานและเรียกใช้ฟังก์ชันในการทดแทนคำสั่ง: $(valNum "$num")
  • กำหนดให้กับหนึ่งหรือหลายตัวแปรภายในฟังก์ชั่นและอ่านตัวแปรเหล่านั้นในภายหลัง

2

ฉันมีผลลัพธ์ที่ขัดแย้งกันในพื้นที่นี้ด้วยตัวเอง นี่คือผลลัพธ์จากการทดลองเชิงประจักษ์ของฉัน ประการแรก ' ทฤษฎี ' บางคำเกี่ยวกับคำสั่ง bash หรือ * nix:

  • สำเร็จ == 0 ... กล่าวคือ ไม่มีรหัสสถานะข้อผิดพลาด)
  • FAIL! = 0 ...... รหัสสถานะบางส่วน

ตัวอย่าง:

if  ls -lt /nonexistantdir
then 
    echo "found"
else
    echo "FAIL"
fi
#
echo
ls -lt /nonexistantdir; echo "status = $?"
echo "status = $?"

เอาท์พุท:

ls: cannot access '/nonexistantdir': No such file or directory
FAIL... 

ls: cannot access '/nonexistantdir': No such file or directory
status = 2

ดังที่แสดงlsคำสั่งส่งคืนรหัสสถานะ = 2 เมื่อคุณลองไดเรกทอรีที่ถูกต้องสถานะจะเป็นศูนย์ ( 0 ) ไม่เหมือนกับภาษาอื่นเกือบทั้งหมด

กฎ # 1 - สร้าง ...

  • TRUE == 0
  • FALSE! = 0

เราต้องจำไว้ว่าเรากำลังทดสอบรหัสข้อผิดพลาดในifคำสั่งBash ฉันตั้งค่าคงที่หรือคุณสามารถใช้เชลล์trueหรือfalseคำสั่ง

TRUE=0
FALSE=1

#  valid number function
#
valNum()
{
    flag=$TRUE

    if [[ $1 != [1-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9] ]]; then
        echo "Invalid Number"
        flag=$FALSE
    fi
    return $flag
}

#    later on ...
#
if validNum Abc 
then
    echo "Lucky number"
else
    echo "Not lucky."
fi

และเอาท์พุท:

Invalid Number
Not lucky.

อย่างไรก็ตามฉันแนะนำให้คุณให้ ' up-vote ' @Gilles เพราะคำตอบของเขาคือคำตอบที่ถูกต้อง ฉันแค่ต้องการลดความเรียบง่ายของ ePaper ลง

อีกสิ่งหนึ่งtestคำสั่ง ดูเหมือนว่า:

[[ some-expression ]]; 

เวลาส่วนใหญ่. และตัวอย่างเช่น:

$ test 1
$ echo "result = $?"
result = 0
$ test 0
$ echo "result = $?"
result = 0

ศูนย์ (0) เป็นจริง ทำไม? หน้าคนบอกว่าอาร์กิวเมนต์เดียวคือ ' จริง ' เมื่อไม่เป็นโมฆะ

อ้างอิง:

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