อ้างถึงตัวแปรในเชลล์สคริปต์“ ถ้า” คำสั่ง


9

เช่น

if [ "$FOO" = "true" ]; then

VS

if [ $FOO = "true" ]; then

ความแตกต่างคืออะไร? ดูเหมือนว่าทั้งสองคำสั่งใช้งานได้เช่นกัน


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

@DennisWilliamson ไม่มากคุณจำเป็นต้องมีเครื่องหมายคำพูดทางด้านขวาของตัวดำเนินการที่ตรงกัน (ใน) และการจับคู่รูปแบบ
Gilles 'หยุดความชั่วร้าย'


@Gilles: บางครั้งไม่ สำหรับสตริงตัวอักษรที่มีช่องว่างหรือสตริงตัวอักษรหรือตัวแปรที่มีตัวอักษร glob ที่คุณต้องการที่จะดำเนินการอย่างแท้จริง , a='foo bar'; [[ $a == "foo bar" ]]ด้านขวาจะต้องถูกยกมา: อย่างไรก็ตามตัวแปรที่ไม่ประกอบด้วยอักขระ glob [[ $a == $a ]]ไม่จำเป็นต้องเป็น: การขยายคำไม่ได้ดำเนินการภายในวงเล็บเหลี่ยมสองชั้น และสำหรับการจับคู่ regex รูปแบบทางด้านขวามือจะต้องไม่ถูกยกมาหรือมันจะถูกนำมาเป็นสตริงตัวอักษร: [[ $a =~ .*oo.*r ]](รูปแบบควรอยู่ในตัวแปรยกเลิกการยกอย่างไรก็ตามแทน ...
หยุดชั่วคราวจนกว่าจะแจ้งให้ทราบต่อไป

ของการเป็นนิติบุคคลอย่างแท้จริงที่นี่) สำหรับ glob สไตล์จับคู่รูปแบบตัวอักษร glob [[ $a == foo* ]]จะต้องไม่ถูกยกมาไม่ว่าจะเป็นตัวอักษรหรือในตัวแปร: คุณสามารถให้ตัวอย่างเพิ่มเติมของข้อกำหนดสำหรับการอ้างอิงนอกเหนือจากตัวอย่างสตริงตัวอักษรของฉันได้หรือไม่?
หยุดชั่วคราวจนกว่าจะมีการแจ้งให้ทราบต่อไป

คำตอบ:


6

หากค่าของ$FOOเป็นคำเดียวที่ไม่มีอักขระตัวแทน\[*?ดังนั้นทั้งสองจะเหมือนกัน

หาก$FOOไม่ได้ถูกมอบหมายหรือว่างเปล่าหรือมากกว่าหนึ่งคำ (เช่นมีช่องว่างหรือ$IFS) ดังนั้นเวอร์ชันที่ไม่ได้ระบุนั้นเป็นข้อผิดพลาดทางไวยากรณ์ หากเกิดขึ้นเป็นเพียงลำดับของคำที่ถูกต้อง (เช่น0 -eq 0 -o false) ผลลัพธ์อาจเป็นไปตามอำเภอใจ ดังนั้นจึงเป็นการดีที่จะอ้างอิงตัวแปรในเชลล์สคริปต์เสมอ

อนึ่ง"true"ไม่จำเป็นต้องเสนอราคา


3

เพื่อแสดงให้เห็นถึงปัญหาที่อาจทำให้เกิดปัญหานี่คือตัวอย่างเล็ก ๆ น้อย ๆ

สมมติว่าเรามีตัวแปรสองตัวดังนี้:

FOO="some value"
BAR="some value"

ตอนนี้เรามีตัวแปรสองตัวที่เก็บสตริง / ค่าเดียวกันเอาไว้ ถ้าเราทำบางอย่างถ้างบเพื่อทดสอบผลลัพธ์ในกรณีของคุณ:

if [ $FOO = "$BAR" ]; then echo "match"; else echo "no match"; fi

bash: [: too many argumentsจุดนี้คุณจะได้รับ unquoted $ FOO '[ , some , value'ถือตอนนี้สามค่าคือ [คำหลักทดสอบไม่ทราบว่าต้องดำเนินการอะไรเพราะคาดว่าอาร์กิวเมนต์แรกหรืออาร์กิวเมนต์ที่สองจะเป็นโอเปอเรเตอร์

เมื่อเราเสนอราคา "$ FOO" เราจะบอกifให้คุณดูค่าที่เหมาะสมโดยที่ไม่มีการแยกคำเกิดขึ้น

ตัวอย่างอื่น:

my_file="A random file.txt"
  • การทำrm $my_fileหมายถึงการลบ 'A' 'random' 'file.txt' ซึ่งทำให้เป็นสามไฟล์
  • การทำrm "$my_file"จะลบ "A file.txt แบบสุ่ม" ซึ่งสร้างหนึ่งไฟล์

หวังว่าฉันจะไม่ทำให้คุณสับสนกับตัวอย่างเหล่านี้


0

ในกรณีเฉพาะนี้ไม่มีความแตกต่าง

อย่างไรก็ตามหาก$FOOมีช่องว่างหรืออักขระพิเศษบางอย่างคุณจะมีปัญหา

ใน"$FOO"กรณีนี้มันจะใช้ตัวแปรโดยรวมเพื่อทำการจับคู่ที่ป้องกันคุณจากปัญหาพื้นที่

อย่างไรก็ตามหากคุณใช้$FOOและมีกรณีพิเศษมันจะส่งผลกระทบต่อคำสั่ง if

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