การมอบหมายเป็นเหมือนคำสั่งที่มีสถานะการออกยกเว้นเมื่อมีการทดแทนคำสั่ง?


10

ดูตัวอย่างต่อไปนี้และผลลัพธ์ใน POSIX เชลล์:

  1. false;echo $?หรือfalse || echo 1:1
  2. false;foo="bar";echo $?หรือfoo="bar" && echo 0:0
  3. foo=$(false);echo $?หรือfoo=$(false) || echo 1:1
  4. foo=$(true);echo $?หรือfoo=$(true) && echo 0:0

ตามที่ระบุไว้โดยคำตอบที่ได้รับการโหวตสูงสุดที่/programming/6834487/what-is-the-variable-in-shell-scripting :

$? ถูกใช้เพื่อค้นหาค่าส่งคืนของคำสั่งที่เรียกใช้งานครั้งสุดท้าย

นี่อาจเป็นความเข้าใจผิดเล็กน้อยในกรณีนี้ดังนั้นขอนิยาม POSIX ซึ่งอ้างถึงในโพสต์จากกระทู้นั้น:

? ขยายเป็นสถานะทางออกทศนิยมของไปป์ไลน์ล่าสุด (ดูที่ Pipelines)

ดังนั้นดูเหมือนว่าการมอบหมายตัวเองนับเป็นคำสั่ง (หรือมากกว่าส่วนท่อ) ที่มีค่าศูนย์ทางออก แต่จะใช้ก่อนที่ด้านขวาของการมอบหมาย (เช่นการทดแทนคำสั่งเรียกในตัวอย่างของฉันที่นี่)

ฉันเห็นว่าพฤติกรรมนี้เหมาะสมจากมุมมองเชิงปฏิบัติ แต่ดูเหมือนว่าฉันค่อนข้างผิดปกติที่งานมอบหมายจะนับตามลำดับนั้น อาจจะชัดเจนมากกว่านี้ทำไมมันแปลกสำหรับฉันลองสมมติว่าการบ้านเป็นหน้าที่:

ASSIGNMENT( VARIABLE, VALUE )

แล้วfoo="bar"จะเป็น

ASSIGNMENT( "foo", "bar" )

และfoo=$(false)จะเป็นเช่นนั้น

ASSIGNMENT( "foo", EXECUTE( "false" ) )

ซึ่งหมายความว่าการEXECUTEรันครั้งแรกและครั้งเดียวหลังจากนั้น ASSIGNMENTจะทำงาน แต่ก็ยังคงEXECUTEสถานะที่สำคัญที่นี่

ฉันถูกต้องในการประเมินของฉันหรือฉันเข้าใจผิด / ขาดอะไรไปหรือเปล่า? นี่คือเหตุผลที่ถูกต้องสำหรับฉันที่ดูพฤติกรรมนี้ว่า "แปลก" หรือไม่?


1
ขออภัย แต่มันก็ไม่ชัดเจนสำหรับฉันในสิ่งที่คุณพบว่าแปลก
Kusalananda

1
@ Kusalananda บางทีมันอาจจะช่วยบอกคุณได้ว่ามันเริ่มต้นด้วยฉันถามตัวเองว่า: "ทำไมfalse;foo="bar";echo $?กลับมาเป็น 0 เสมอเมื่อคำสั่งจริงล่าสุดที่รันคือfalse" โดยพื้นฐานแล้วการบ้านนั้นมีพฤติกรรมพิเศษเมื่อพูดถึงรหัสทางออก รหัสการออกของพวกเขาคือ 0 เสมอยกเว้นเมื่อไม่ใช่เพราะสิ่งที่วิ่งเป็นส่วนหนึ่งทางด้านขวามือของการมอบหมาย
phk

1
ที่เกี่ยวข้อง: stackoverflow.com/questions/20157938/…
Kusalananda

คำตอบ:


10

ออกจากสถานะสำหรับการมอบหมายงานเป็นที่แปลกประหลาด readonlyวิธีที่ชัดเจนที่สุดสำหรับงานที่จะล้มเหลวคือถ้าตัวแปรเป้าหมายมีการทำเครื่องหมาย

$ err(){ echo error ; return ${1:-1} ; }
$ PS1='$? $ '
0 $ err 42
error
42 $ A=$(err 12)
12 $ if A=$(err 9) ; then echo wrong ; else E=$? ; echo "E=$E ?=$?" ; fi
E=9 ?=0
0 $ readonly A
0 $ if A=$(err 10) ; then echo wrong ; else E=$? ; echo "E=$E ?=$?" ; fi
A: is read only
1 $

โปรดทราบว่าไม่ได้ใช้ทั้งเส้นทางจริงและเท็จของคำสั่ง if การมอบหมายล้มเหลวหยุดการดำเนินการของคำสั่งทั้งหมด bash ในโหมด POSIX และ ksh93 และ zsh จะยกเลิกสคริปต์ทั้งหมดหากการมอบหมายล้มเหลว

หากต้องการอ้างอิงมาตรฐาน POSIX ในสิ่งนี้ :

คำสั่งที่ไม่มีชื่อคำสั่ง แต่คำสั่งที่มีการทดแทนคำสั่งมีสถานะการออกจากการทดแทนคำสั่งสุดท้ายที่เชลล์ดำเนินการ

นี่เป็นส่วนหนึ่งของไวยากรณ์เชลล์ที่เกี่ยวข้อง

 foo=$(err 42)

ซึ่งมาจากsimple_command(simple_command → cmd_prefix → ASSIGNMENT_WORD) ดังนั้นหากการมอบหมายสำเร็จสถานะการออกจะเป็นศูนย์เว้นแต่การทดแทนคำสั่งเกี่ยวข้องในกรณีนี้สถานะการออกคือสถานะของสถานะสุดท้าย หากการมอบหมายล้มเหลวสถานะการออกไม่เป็นศูนย์ แต่คุณอาจไม่สามารถตรวจจับได้


1
หากต้องการเพิ่มคำตอบของคุณนี่คือคำตอบจากเธรดอื่นที่มีการอ้างอิงมาตรฐาน POSIX ที่ใหม่กว่าบนนี้ข้อสรุปนั้นเหมือนกันโดยทั่วไป: unix.stackexchange.com/a/270831/117599
phk

4

คุณพูด,

... ดูเหมือนว่าการมอบหมายนั้นถือเป็นคำสั่ง ... โดยมีค่าการออกเป็นศูนย์ แต่จะใช้ก่อนที่ด้านขวาของการมอบหมาย (เช่นการแทนที่คำสั่งเรียก…)

นั่นไม่ใช่วิธีที่ดีในการดู แต่มันเป็นเรื่องธรรมดาเล็กน้อย สถานะการคืนสินค้าโดยรวมจาก

A = $ ( cmd 1 ) B = $ ( cmd 2 ) C = $ ( cmd 3 ) D = $ ( cmd 4 ) E = mc 2
เป็นสถานะออกจาก การกำหนดที่เกิดขึ้นหลังจากการกำหนดไม่ได้ตั้งค่าสถานะการออกโดยรวมเป็น 0cmd4E=D=

นอกจากนี้เมื่ออิคารัส ชี้ให้เห็นตัวแปรสามารถกำหนดให้อ่านได้อย่างเดียว พิจารณารูปแบบต่อไปนี้ในตัวอย่างของอิคารัส:

$ err() { echo "stdout $*"; echo "stderr $*" >&2; return ${1:-1}; }
$ readonly A
$ Z=$(err 41 zebra) A=$(err 42 antelope) B=$(err 43 badger)
stderr 41 zebra
stderr 42 antelope
bash: A: readonly variable
$ echo $?
1
$ printf "%s = %s\n" Z "$Z" A "$A" B "$B"
Z = stdout 41 zebra
A =
B =
$

แม้ว่าจะAเป็นแบบอ่านอย่างเดียว bash จะดำเนินการแทนคำสั่งทางด้านขวาของA=- จากนั้นให้ยกเลิกคำสั่งAนั้นเนื่องจากอ่านได้อย่างเดียว สิ่งนี้ขัดแย้งกับการตีความของคุณเพิ่มเติมว่ามูลค่าการออกของการมอบหมายใช้ก่อนทางด้านขวาของการมอบหมาย

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