อะไรคือความแตกต่างระหว่างไวยากรณ์ $ () และวงเล็บปีกกา $ {} ใน Makefile


111

มีความแตกต่างใด ๆ ในการเรียกใช้ตัวแปรมีไวยากรณ์${var}และ$(var)? ตัวอย่างเช่นตัวแปรจะขยายหรืออะไร?

คำตอบ:


95

ไม่มีความแตกต่าง - หมายความว่าเหมือนกันทุกประการ (ใน GNU Make และใน POSIX make)

ฉันคิดว่า$(round brackets)มันดูเป็นระเบียบกว่า แต่นั่นเป็นเพียงความชอบส่วนตัว

(คำตอบอื่น ๆ ชี้ไปที่ส่วนที่เกี่ยวข้องของเอกสารประกอบ GNU และโปรดทราบว่าคุณไม่ควรผสมไวยากรณ์ภายในนิพจน์เดียว)


11
ฉันใช้$()in make เพื่อหลีกเลี่ยงไม่ให้ตัวเองสับสน (มากกว่าที่มีอยู่แล้ว) ระหว่างตัวแปร make และ shell เอกสารยี่ห้อ GNU ในการอ้างอิงตัวแปร
Etan Reisner

ขอบคุณผู้ใช้ @Eloy ที่แนะนำการขยายคำตอบนี้แม้ว่าฉันจะปฏิเสธบทสรุปของพวกเขาเพราะเพียงแค่สังเกตคะแนนพิเศษที่มีค่าในคำตอบอื่น ๆ
Norman Grey

1
เครื่องมือบางอย่างอาจไม่ให้เกียรติความเหมือนกัน IntelliJ IDEA เน้นdeploy: ${DEPS}ว่าเป็นข้อผิดพลาดทางไวยากรณ์สำหรับฉัน แต่แสดงdeploy: $(DEPS)ว่าถูกต้องแม้ว่าการสะกดทั้งสองจะมีผลเหมือนกันเมื่อเรียกเข้าmakeมา
amacleod

47

พื้นฐานของตัวแปรอ้างอิงส่วนจากGNU makeรัฐเอกสารไม่มีความแตกต่าง :

ในการแทนที่ค่าของตัวแปรให้เขียนเครื่องหมายดอลลาร์ตามด้วยชื่อของตัวแปรในวงเล็บหรือวงเล็บปีกกา: อย่างใดอย่างหนึ่ง$(foo)หรือ ${foo}เป็นการอ้างอิงที่ถูกต้องสำหรับตัวแปร foo


14

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

จากGNU ทำให้คู่มือเกี่ยวกับ Function Call Syntax (เน้นของฉัน):

[…] หากอาร์กิวเมนต์มีการเรียกใช้ฟังก์ชันอื่น ๆ หรือการอ้างอิงตัวแปรก็เป็นการดีที่สุดที่จะใช้ตัวคั่นชนิดเดียวกันสำหรับการอ้างอิงทั้งหมด เขียนไม่ได้$(subst a,b,$(x)) $(subst a,b,${x})นี้เป็นเพราะมันเป็นที่ชัดเจนและเพราะเพียงหนึ่งชนิดของตัวคั่นจะถูกจับคู่เพื่อหาจุดสิ้นสุดของการอ้างอิง


11

จริงๆแล้วดูเหมือนว่าจะแตกต่างกันพอสมควร:

, = ,
list = a,b,c
$(info $(subst $(,),-,$(list))_EOL)
$(info $(subst ${,},-,$(list))_EOL)

เอาต์พุต

a-b-c_EOL
md/init-profile.md:4: *** unterminated variable reference. Stop.

แต่จนถึงตอนนี้ฉันพบความแตกต่างนี้ก็ต่อเมื่อชื่อตัวแปรใน $ {... } มีเครื่องหมายจุลภาค ตอนแรกฉันคิดว่า $ {... } กำลังขยายเครื่องหมายจุลภาคไม่ได้เป็นส่วนหนึ่งของค่า แต่ปรากฎว่าฉันไม่สามารถแฮ็คได้ด้วยวิธีนี้ ฉันยังไม่เข้าใจเรื่องนี้ ... หากใครมีคำอธิบายฉันยินดีที่จะทราบ!


จากคำตอบของ Edouard ซึ่งตั้งข้อสังเกตว่า GNU จัดทำเอกสารระบุว่าไม่มีความแตกต่างฉันเดาว่านี่อาจเป็นเพียงข้อบกพร่อง
Keith M

8
ตามที่ระบุไว้ในคำตอบของ Alexandre Perrin ไม่ควรผสมทั้งสองไวยากรณ์ในบรรทัดเดียวกัน
lenz

11

สไตล์ $ {} ช่วยให้คุณสามารถทดสอบกฎการสร้างในเชลล์ได้หากคุณมีตัวแปรสภาพแวดล้อมที่กำหนดไว้เนื่องจากมันเข้ากันได้กับ bash


4

จะสร้างความแตกต่างหากนิพจน์มีวงเล็บที่ไม่สมดุล:

${info ${subst ),(,:-)}}
$(info $(subst ),(,:-)))

->

:-(
*** insufficient number of arguments (1) to function 'subst'.  Stop.

สำหรับการอ้างอิงตัวแปรสิ่งนี้สร้างความแตกต่างสำหรับฟังก์ชันหรือสำหรับชื่อตัวแปรที่มีวงเล็บ (คิดไม่ดี)

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