การใช้งาน set -u ไม่ทำงานอย่างที่คาดไว้


12

ฉันเรียนรู้วิธีใช้setตัวเลือกต่างๆ ในสคริปต์อย่างมีประสิทธิภาพและพบset -uว่าเหมาะสำหรับการออกจากสคริปต์หากตัวแปรไม่ได้รับการตั้งค่าอย่างเหมาะสม (เช่นการลบผู้ใช้) ตามหน้าmanset -uและset -eทำสิ่งต่อไปนี้ ...

-e  Exit immediately if a command exits with a non-zero status.
-u  Treat unset variables as an error when substituting.

ฉันสร้างสคริปต์ทดสอบเพื่อทดสอบฟังก์ชันนี้ แต่ดูเหมือนว่าจะไม่ทำงานตามที่คาดไว้ บางทีใครบางคนสามารถอธิบายปัญหาของฉันกับฉันได้ดีกว่าและฉันกำลังตีความผิด ๆ อยู่ที่ไหน? สคริปต์ทดสอบอยู่ด้านล่าง ขอขอบคุณ.

set -e
set -u
testing="This works"
echo $?
echo ${testing}
testing2=
echo $?
echo ${testing2}
testing3="This should not appear"
echo $?
echo ${testing3}

ฉันคาดหวังให้สคริปต์แสดง0และ"ใช้งานได้"แล้วล้มเหลวเนื่องจาก${testing2}ไม่ได้ตั้งค่า

ฉันแสดงเป็น0และ"ใช้งานได้"แทนตามด้วย0จากนั้น0 แสดงว่าไม่ควรปรากฏ

มีใครให้ความรู้บ้างไหม? ขอขอบคุณ.


1
ดังนั้นการติดตาม ... มีวิธีใดที่จะทำให้การตั้งค่าตัวแปรเป็นสายอักขระที่ผิดกฎหมาย / เกิดข้อผิดพลาด? ฉันคาดเดาไม่ได้
ลุคเดวิส

คำตอบ:


10

จาก "man Bash":

พารามิเตอร์ถูกตั้งค่าหากได้รับการกำหนดค่า สตริง Null เป็นค่าที่ถูกต้อง เมื่อตั้งค่าตัวแปรแล้วมันอาจถูกยกเลิกการตั้งค่าโดยใช้คำสั่ง unset builtin เท่านั้น

เมื่อคุณtesting2=ตั้งค่าตัวแปรเป็นสตริงว่าง

เปลี่ยนเป็นunset testing2และลองอีกครั้ง


set -eไม่ได้ช่วยในกรณีนี้เป็นงานที่ไม่เคยมีรหัสทางออกของ 1. ลองนี้จะเห็นว่าคำสั่งสุดท้ายดำเนินการ (ที่ได้รับมอบหมาย) มีรหัสทางออกของ 0 หรืออ่านคำถามนี้ :

$ false; a=""; echo $?
0

และฉันก็เชื่อว่าการใช้ set -e นั้นเป็นปัญหาที่ทางออกมากกว่า

สิ่งที่อาจได้รับข้อผิดพลาดจากการใช้ตัวแปร unset คือset -u:

#!/bin/bash
set -u
testing="This works"
echo ${testing}
unset testing2
echo ${testing2}
testing3="This should not appear"
echo ${testing3}

จะส่งออก:

$  ./script.sh
This works
./script.sh: line 9: testing2: unbound variable

3

testing2=ตั้งค่าtesting2ตัวแปรเป็นสตริงว่าง ตัวแปรถูกตั้งค่าจริง

อย่างไรก็ตามหากคุณต้องทำงานecho $testing99ในเชลล์ Bash แบบโต้ตอบ (โดยไม่มีการตั้งค่าerrexitเช่นset -e) คุณจะได้รับข้อผิดพลาด:

bash: testing99: unbound variable

นอกเหนือ

ขณะที่การทดสอบสคริปต์เพียงแค่ตอนนี้ผมค้นพบว่าการโต้ตอบเปลือก ไม่เคยออกเมื่อพยายามที่จะขยายตัวแปรที่ยังไม่ได้รับการติดตั้งในขณะที่ไม่โต้ตอบเปลือก (ทำงานสคริปต์เปลือก) ทางออกเสมอ ตามหน้า man POSIX สำหรับset:

-u เชลล์จะเขียนข้อความถึงข้อผิดพลาดมาตรฐานเมื่อมันพยายามที่จะขยายตัวแปรที่ไม่ได้ตั้งค่าและออกทันที เชลล์เชิงโต้ตอบจะต้องไม่ออก

การโต้ตอบทุบตีเปลือกจะไม่ออกจากเว้นแต่errexitมียังได้รับชุด ในขณะที่เปลือกประแบบโต้ตอบจะไม่ออก - แม้ว่าจะset -eได้รับการเรียกใช้ก่อนหน้านี้


หากเส้นประไม่ได้ออกด้วย set -e; set -u; ไม่ได้ตั้งค่า aa; echo $ aa จากนั้น dash ไม่ถูกต้อง
schily

@ schily เมื่อฉันสังเกตเห็นสิ่งนี้เป็นครั้งแรกฉันคิดว่าผู้เขียนขีดรู้ดีกว่าฉันและอาจมีความกำกวมในข้อกำหนด POSIX แต่มีการตรวจสอบอีกครั้งpubs.opengroup.org/onlinepubs/9699919799/utilities/ …ฉัน ยอมรับว่าดูเหมือนว่ามีข้อผิดพลาดเอาล่ะ
Anthony Geoghegan

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