ในเชลล์สคริปต์ถ้าฉันกำหนดตัวแปรเช่นFOO=25มีความแตกต่างระหว่างการอ้างอิงเป็น$FOO$และ${FOO}$?
ในเชลล์สคริปต์ถ้าฉันกำหนดตัวแปรเช่นFOO=25มีความแตกต่างระหว่างการอ้างอิงเป็น$FOO$และ${FOO}$?
คำตอบ:
ในสถานการณ์ส่วนใหญ่ทั้งสอง$varและ${var}เหมือนกัน (โปรดทราบว่าคุณจะต้องไม่ใช้$ท้าย!)
ตัวอย่างหนึ่งที่คุณต้องการวงเล็บปีกกาคือเมื่อคุณต้องการใส่ตัวแปรในสายอักขระต่อเนื่อง
ตัวอย่าง:
var=hel
echo ${var}lo
helloออกจะ
ที่จะตอบคำถามหลักของคุณ${foo}เรียกว่า"การขยายตัวพารามิเตอร์" เพื่อความแม่นยำ$ตัวเองจะเริ่มการขยายตัวของพารามิเตอร์ตัว{ }เลือกจริงตามข้อกำหนด POSIXแต่มีประโยชน์ในการระบุจุดสิ้นสุดของชื่อตัวแปร:
$ foo="bar"
$ echo $fooBaz ## fails, no variable named $fooBaz exists
$ echo ${foo}Baz ## works, $foo is expanded and the string Baz is appended
barBaz
โดยทั่วไป$fooและ${foo}เหมือนกัน นอกเหนือจากกรณีเช่นข้างต้นหรือเมื่อคุณทำการจัดการสตริงพวกเขาจะเทียบเท่าอย่างสมบูรณ์
อย่างไรก็ตามคุณไม่ควรใช้อย่างใดอย่างหนึ่ง กฎของหัวแม่มือคือว่ามีข้อยกเว้นน้อยมากที่คุณควรเสมอใช้"$foo"หรือ"${foo}"และไม่เคยหรือ$foo ${foo}คุณควรอ้างอิงตัวแปรของคุณเสมอเพื่อหลีกเลี่ยงการเรียกใช้ตัวดำเนินการแยก + glob (เพิ่มเติมในภายหลัง) $foo$แน่นอนคุณไม่ต้องการ รอบชิงชนะเลิศ$ไม่เกี่ยวข้อง:
$ foo="bar"
$ echo "$foo$"
bar$
ดังนั้นในขณะที่ตัวแปร unquote บางครั้งก็โอเค:
$ echo $foo
bar
พวกเขามักจะไม่และควรหลีกเลี่ยงจริง ๆ :
$ if [ -n $foo ]; then echo empty; else echo "not empty"; fi ## fails
empty
$ if [ -n "$foo" ]; then echo empty; else echo "not empty"; fi ## works
not empty
โปรดทราบว่าวงเล็บไม่ได้ช่วยที่นี่:
$ if [ -n ${foo} ]; then echo empty; else echo "not empty"; fi ## fails
empty
$ if [ -n "${foo}" ]; then echo empty; else echo "not empty"; fi ## works
not empty
เมื่อคุณใช้$fooหรือ${foo}เชลล์จะแบ่งค่าที่บันทึกไว้ในตัวแปรในช่องว่าง (ซึ่งสามารถเปลี่ยนแปลงได้โดยการตั้งค่าIFSตัวแปรเป็นอย่างอื่น) ลงในรายการจากนั้นแต่ละองค์ประกอบของรายการจะถือว่าเป็นรูปแบบกลมและขยายเป็น ไฟล์หรือไดเรกทอรีที่ตรงกัน นี้เป็นที่รู้จักกันแยก + globผู้ประกอบการ หากต้องการแสดงตัวอย่างให้พิจารณาไดเร็กทอรีที่มีสองไฟล์:
$ ls -l
-rw-r--r-- 1 terdon terdon 0 Oct 9 18:16 file1
-rw-r--r-- 1 terdon terdon 0 Oct 9 18:16 file2
ตอนนี้เรามาตั้งค่าตัวแปรเป็นfoo *:
$ foo="foo *"
จะเกิดอะไรขึ้นถ้าเราพยายามตรวจสอบว่ามีไฟล์ชื่อนั้นอยู่หรือไม่?
$ if [ -e $foo ]; then echo "file exists"; else echo "no such file"; fi
file exists
ตัวแปรถูกแบ่งออกเป็นfooและ*เนื่องจาก*เป็น wildcard ที่ตรงกับสตริงใด ๆ เชลล์จะบอกคุณว่าไฟล์ชื่อfoo *exxists อย่างไรก็ตามหากเราพูดอย่างถูกต้องสิ่งนี้จะไม่เกิดขึ้น:
$ if [ -e "$foo" ]; then echo "file exists"; else echo "no such file"; fi
no such file
นั่นเป็นตัวอย่างเล็กน้อยเพื่อแสดงจุด ลองคิดดูหากผมใช้rmแทนechoแม้ว่า
ดังนั้นกฎข้อแรก: อ้างอิงตัวแปรของคุณเสมอ คุณสามารถใช้อย่างใดอย่างหนึ่ง"$foo"หรือ"${foo}"แต่อ้างอิงมันด้วยวิธีใดวิธีหนึ่ง สำหรับรายละเอียดเพิ่มเติมเกี่ยวกับการใช้ตัวแปรอย่างปลอดภัยดูที่โพสต์เหล่านี้:
$ var="foo *"จะเป็น$ foo="foo *"? คุณไม่ได้ใช้varทุกที่
$ในที่สุด! มันจะถือว่าเป็นตัวอักษรปกติและไม่เป็นส่วนหนึ่งของชื่อตัวแปร