บันทึกรหัสออกในภายหลัง


15

ดังนั้นฉันจึงมีสคริปต์เล็กน้อยสำหรับการทดสอบบางอย่าง

javac *.java && java -ea Test
rm -f *.class

ตอนนี้ปัญหาของเรื่องนี้ก็คือเมื่อฉันเรียกใช้สคริปต์./testก็จะส่งกลับรหัสทางออกที่ประสบความสำเร็จแม้ว่าการทดสอบล้มเหลวเพราะrm -f *.classประสบความสำเร็จ

วิธีเดียวที่ฉันสามารถคิดให้มันทำในสิ่งที่ฉันต้องการรู้สึกน่าเกลียด:

javac *.java && java -ea Test
test_exit_code=$?
rm -f *.class
if [ "$test_exit_code" != 0 ] ; then false; fi

แต่ดูเหมือนว่ามีปัญหาบางอย่างที่พบได้ทั่วไป - ทำงานทำความสะอาดแล้วส่งคืนรหัสทางออกของงานต้นฉบับ

อะไรคือวิธีที่ใช้สำนวนที่สุดในการทำสิ่งนี้ (โดยทั่วไปคือทุบตีหรือแค่กระสุน)?

คำตอบ:


5

คุณสามารถใส่คำสั่งexitและrmคำสั่งลงในคำสั่งแบบง่าย ๆ ด้วยคำสั่งevallike:

java ... && java ...
eval "rm -f *.class; exit $?"

$?คุณค่าของวิธีนั้นเมื่อถูกส่งไปยังexitสิ่งที่มันได้รับมอบหมายทันทีก่อนที่จะevalวิ่ง


evalเป็นที่ชื่นชอบของแฟน ๆ เสมอ
mikeserv

23

ฉันจะไปกับ:

javac *.java && java -ea Test
test_exit_code=$?
rm -f *.class
exit "$test_exit_code"

เหตุใดจึงต้องกระโดดเมื่อexitมี


คุณสามารถใช้trap:

trap 'last_error_code=$?' ERR

ตัวอย่างเช่น:

$ trap 'last_error_code=$?' ERR
$ false
$ echo $?
1
$ echo $last_error_code $?
1 0

ฉันเห็นด้วยว่ามันดีกว่าของฉัน แต่ก็ยังรู้สึกไม่พึงพอใจที่ฉันต้องเก็บรหัสทางออกไว้อย่างชัดเจน ไม่มีวิธีใดที่จะ 'ดัน' รหัสทางออกและ 'pop' อีกครั้งในภายหลัง?
math4tots

@ math4tots ลองอัปเดต
muru

ดังนั้นด้วยการอัปเดตของคุณฉันจะต้องเริ่มต้น last_error_code ให้เป็นศูนย์แล้วกลับมาที่จุดสิ้นสุดดังนั้นฉันจะมีรหัสทางออกที่ไม่เป็นศูนย์หากคำสั่งใดโยนข้อผิดพลาด? มันเป็นเคล็ดลับสุดเจ๋ง แต่สำหรับสคริปต์แฮ็กสองบรรทัดของฉันฉันคิดว่าฉันชอบคำตอบของ @mikeserv
math4tots

@ math4tots exit ${last_error_code:=0}คุณสามารถทำ
muru

@avip สำหรับอะไร? มันมีอยู่ในเครื่องหมายคำพูดเดี่ยวดังนั้นตัวแปรจะถูกประเมินเมื่อเรียกกับดักเท่านั้น
muru

9

เท่าที่ฉันรู้สิ่งทุบตีที่ใกล้เคียงที่สุดต้องtry...finallyบล็อกจากภาษาการเขียนโปรแกรม C-like เพิ่มเติม (ซึ่งเป็นสิ่งที่คุณอาจต้องการถ้ามันมี) การtrapก่อสร้างซึ่งทำงานเช่นนี้:

trap "rm -f *.class" EXIT
javac *.java && java -ea Test

สิ่งนี้จะดำเนินการ "rm -f * .class" เมื่อสคริปต์ของคุณออก หากคุณมีสิ่งที่ซับซ้อนกว่านี้คุณสามารถใส่มันลงไปในฟังก์ชั่น:

cleanup() {
    ...
}
trap cleanup EXIT
javac *.java && java -ea Test

หากคุณมีความโน้มเอียงมากคุณสามารถเปลี่ยนให้เป็นสำนวนทั่วไปที่ค่อนข้างเหมือนtry...catch...finallyบล็อกในซีบางอย่างเช่นนี้:

(
  trap "catch_block; exit" ERR
  trap finally_block EXIT
  # contents of try goes here
)

โปรดทราบว่าวงเล็บคั่นขอบเขตย่อย ด้วยโครงสร้างนี้เฉพาะ subshell ออกหากคำสั่งล้มเหลวไม่ใช่สคริปต์ทั้งหมด โปรดจำไว้ว่า subshells ค่อนข้างแพงคำนวณดังนั้นอย่าใช้มากเกินไป (หลายร้อย) ของพวกเขา ขึ้นอยู่กับสคริปต์ของคุณคุณอาจจะได้รับผลกระทบที่เหมือนกันได้อย่างมีประสิทธิภาพยิ่งขึ้นด้วยฟังก์ชั่นเชลล์และtrap ... RETURNแต่ก็ขึ้นอยู่กับคุณที่จะตรวจสอบ

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