ฉันจะทำอะไรแบบนี้ในทุบตีได้อย่างไร
if "`command` returns any error";
then
echo "Returned an error"
else
echo "Proceed..."
fi
ฉันจะทำอะไรแบบนี้ในทุบตีได้อย่างไร
if "`command` returns any error";
then
echo "Returned an error"
else
echo "Proceed..."
fi
คำตอบ:
วิธีทำบางอย่างตามเงื่อนไขหากคำสั่งสำเร็จหรือล้มเหลว
นั่นคือสิ่งที่ifแถลงการณ์ของ bash ทำ:
if command ; then
echo "Command succeeded"
else
echo "Command failed"
fi
การเพิ่มข้อมูลจากความคิดเห็น: คุณไม่จำเป็นต้องใช้ไวยากรณ์[... ]ในกรณีนี้ ตัวเองเป็นคำสั่งมากเกือบเทียบเท่ากับ[ testมันอาจเป็นคำสั่งที่ใช้บ่อยที่สุดในการใช้ifซึ่งสามารถนำไปสู่การสันนิษฐานว่ามันเป็นส่วนหนึ่งของไวยากรณ์ของเชลล์ แต่ถ้าคุณต้องการทดสอบว่าคำสั่งสำเร็จหรือไม่ให้ใช้คำสั่งโดยตรงด้วยifดังที่แสดงด้านบน
แก้ไข: ยกคำถามที่ด้านบนเพื่อความชัดเจน (คำตอบนี้ไม่ปรากฏใกล้ด้านบนของหน้า)
thenสายแยก
if ! command ; then ... ; fiผมคิดว่าคุณหมายถึง [เป็นคำสั่งและมันไม่จำเป็นในกรณีนี้
if [ ! command ]ไม่ได้ดำเนินการcommand; มันจะถือว่าcommandเป็นสตริงและถือว่าเป็นจริงเพราะมันมีความยาวไม่เป็นศูนย์ [เป็นคำพ้องความหมายสำหรับtestคำสั่ง
สำหรับสิ่งเล็ก ๆ ที่คุณต้องการให้เกิดขึ้นหากคำสั่ง shell ใช้งานได้คุณสามารถใช้&&โครงสร้างได้:
rm -rf somedir && trace_output "Removed the directory"
ในทำนองเดียวกันสำหรับสิ่งเล็ก ๆ ที่คุณต้องการให้เกิดขึ้นเมื่อคำสั่งเชลล์ล้มเหลวคุณสามารถใช้||:
rm -rf somedir || exit_on_error "Failed to remove the directory"
หรือทั้งคู่
rm -rf somedir && trace_output "Removed the directory" || exit_on_error "Failed to remove the directory"
อาจไม่ฉลาดนักที่จะทำสิ่งเหล่านี้มาก แต่บางครั้งพวกเขาก็สามารถทำให้การควบคุมมีความชัดเจนมากขึ้น
ตรวจสอบค่า$?ซึ่งประกอบด้วยผลลัพธ์ของการดำเนินการคำสั่ง / ฟังก์ชันล่าสุด:
#!/bin/bash
echo "this will work"
RESULT=$?
if [ $RESULT -eq 0 ]; then
echo success
else
echo failed
fi
if [ $RESULT == 0 ]; then
echo success 2
else
echo failed 2
fi
ifสำนวนของ Bash ฉันชอบคำตอบของ Keith Thompson
ifการทำ เงื่อนไขการควบคุมการไหลใน Bash ทั้งหมดตรวจสอบ$?เบื้องหลัง นั่นคือสิ่งที่พวกเขาทำ การตรวจสอบค่าของมันอย่างชัดเจนนั้นไม่จำเป็นในกรณีส่วนใหญ่และมักจะเป็นปฏิปักษ์มือใหม่
if ! cmdก็โอเค มิฉะนั้นข้อตกลงร่วมกันคือการใช้elseข้อ คุณไม่สามารถว่างเปล่าได้thenแต่บางครั้งคุณก็เห็นthen : nothing; elseว่า:ไม่มีตัวละครสำคัญ trueจะทำงานที่นั่นเช่นกัน
สิ่งนี้ใช้ได้กับฉัน:
command && echo "OK" || echo "NOK"
หากcommandประสบความสำเร็จก็echo "OK"จะถูกดำเนินการและเนื่องจากมันประสบความสำเร็จการดำเนินการหยุดที่นั่น มิฉะนั้น&&จะถูกข้ามและecho "NOK"ถูกดำเนินการ
command && echo "OK" || c=$?; echo "NOK"; $(exit $c)
command && echo "OK" || (c=$?; echo "NOK"; (exit $c))เหรอ?
echo "OK"ส่วนใดส่วนหนึ่งอาจล้มเหลวตัวเองก็จะดีขึ้น:command && (echo "OK"; exit 0) || (c=$?; echo "NOK"; (exit $c))
ควรสังเกตว่าif...then...fiและ&&/ ||ประเภทของวิธีการจัดการกับสถานะทางออกที่ส่งคืนโดยคำสั่งที่เราต้องการทดสอบ (0 เมื่อสำเร็จ); อย่างไรก็ตามคำสั่งบางคำสั่งจะไม่ส่งคืนสถานะการออกที่ไม่ใช่ศูนย์หากคำสั่งล้มเหลวหรือไม่สามารถจัดการกับอินพุตได้ ซึ่งหมายความว่าปกติifและ&&/ ||แนวทางจะไม่ทำงานสำหรับคำสั่งเฉพาะเหล่านั้น
ตัวอย่างเช่นบน Linux GNU fileยังคงออกด้วย 0 หากได้รับไฟล์ที่ไม่มีอยู่เป็นอาร์กิวเมนต์และfindไม่สามารถระบุตำแหน่งผู้ใช้ไฟล์ที่ระบุ
$ find . -name "not_existing_file"
$ echo $?
0
$ file ./not_existing_file
./not_existing_file: cannot open `./not_existing_file' (No such file or directory)
$ echo $?
0
ในกรณีเช่นนี้วิธีที่เป็นไปได้วิธีหนึ่งที่เราสามารถจัดการกับสถานการณ์ได้คือการอ่านstderr/ stdinข้อความเช่นที่ส่งคืนโดยfileคำสั่งหรือแยกวิเคราะห์เอาต์พุตของคำสั่งเช่นfindนี้ สำหรับวัตถุประสงค์นั้นcaseสามารถใช้ข้อความสั่งได้
$ file ./doesntexist | while IFS= read -r output; do
> case "$output" in
> *"No such file or directory"*) printf "%s\n" "This will show up if failed";;
> *) printf "%s\n" "This will show up if succeeded" ;;
> esac
> done
This will show up if failed
$ find . -name "doesn'texist" | if ! read IFS= out; then echo "File not found"; fi
File not found
ข้อผิดพลาดมากที่สุดที่ฉันสามารถทำได้คือ:
RR=$?
ตอนนี้ไม่เพียง แต่สถานการณ์นี้ แต่คนอื่น ๆ ที่คุณอาจเผชิญให้พิจารณา:
$ AA=1 ; if (( "10#0${AA}" == 1 )) ; then echo yes ; else echo no ; fi
ตอบ: ใช่
$ AA=1 ; if (( "10#0${AA}" != 1 )) ; then echo yes ; else echo no ; fi
คำตอบ: ไม่
$ AA=1 ; if (( "10#0${BB}" == 1 )) ; then echo yes ; else echo no ; fi
คำตอบ: ไม่
$ AA=1 ; if (( "10#0${BB}" != 1 )) ; then echo yes ; else echo no ; fi
ตอบ: ใช่
$ AA=1 ; if (( "10#0${BB}" == 0 )) ; then echo yes ; else echo no ; fi
ตอบ: ใช่
เพื่อป้องกันข้อผิดพลาดทุกชนิด
คุณอาจรับรู้ถึงไวยากรณ์ทั้งหมด แต่นี่เป็นเคล็ดลับ:
"blank"nothing${variable}สัญกรณ์ใหม่ที่ทันสมัยสำหรับตัวแปรคือbase-8แต่รอการเพิ่มศูนย์ทำให้จำนวนกลายเป็น คุณจะได้รับข้อผิดพลาดเช่น:
value too great for base (error token is "08")7สำหรับตัวเลขดังกล่าวข้างต้น นั่นคือเมื่อ10#เข้ามาเล่น:10#base-10กองกำลังจำนวนที่จะคุณสามารถทำได้:
if ($( ping 4.4.4.4 -c1 > /dev/null )) ; then
echo "ping response succsess!!!"
fi
pingถูกจับในมุมมองของการเรียกใช้เป็นคำสั่ง แต่เนื่องจากผลลัพธ์ถูกเปลี่ยนเส้นทางไปยัง / dev / null ที่จะเป็นสตริงว่างเสมอ ดังนั้นคุณจะไม่ทำงานอะไรใน subshell ซึ่งหมายความว่าสถานะการออกก่อนหน้า (ของ subshell การแทนที่คำสั่งที่เป็น ping) จะถูกเก็บไว้ เห็นได้ชัดว่าวิธีที่ถูกต้องอยู่if ping ...; thenที่นี่
ตามที่ระบุไว้ที่อื่นในหัวข้อนี้คำถามเดิมโดยทั่วไปตอบตัวเอง นี่คือภาพประกอบที่แสดงว่าifเงื่อนไขอาจซ้อนกัน
ตัวอย่างนี้ใช้ifเพื่อตรวจสอบว่ามีไฟล์อยู่หรือไม่และเป็นไฟล์ปกติหรือไม่ หากเงื่อนไขเหล่านั้นเป็นจริงให้ตรวจสอบว่ามีขนาดใหญ่กว่า 0 หรือไม่
#!/bin/bash
echo "Which error log are you checking today? "
read answer
if [ -f /opt/logs/$answer*.errors ]
then
if [ -s /opt/logs/$answer*.errors ]
then
echo "Content is present in the $answer error log file."
else
echo "No errors are present in the $answer error log file."
fi
else
echo "$answer does not have an error log at this time."
fi
#!/bin/bash
if command-1 ; then
echo "command-1 succeeded and now running from this block command-2"
command-2
else
echo "command-1 failed and now running from this block command-3"
command-3
fi
สิ่งนี้สามารถทำได้ง่ายๆด้วยวิธีนี้เนื่องจาก$?ให้สถานะของคำสั่งสุดท้ายที่ถูกเรียกใช้งาน
ดังนั้นมันอาจจะเป็น
#!/bin/sh
... some command ...
if [ $? == 0 ] ; then
echo '<the output message you want to display>'
else
echo '<failure message>'
fi