POSIX shell: `$ 'สูญเสียความหมายพิเศษหรือไม่ถ้ามันเป็นตัวอักษรตัวสุดท้ายในคำ?


17

ที่เถ้าถ่านประและทุบตีเมื่อฉันวิ่ง

$ echo ab$

มันกลับมา

ab$

พฤติกรรมนี้ถูกระบุโดย POSIX หรือเป็นเพียงการประชุมทั่วไปในเปลือกหอยที่สอดคล้องกับ POSIX หรือไม่ ฉันไม่พบสิ่งใดในหน้าภาษาคำสั่งเชลล์ POSIX ที่กล่าวถึงพฤติกรรมนี้


4
คำถามที่ดีกว่าคือ " $ ได้รับความหมายพิเศษหรือไม่ถ้าเป็นตัวอักษรสุดท้ายในคำเดียว" ไม่มีความหมายพิเศษเดียวที่กำหนดให้$; มันจะถูกใช้ในการแนะนำหลาย แต่ที่แตกต่างกันการขยายเช่นการขยายตัวพารามิเตอร์${...}แทนคำสั่งและการแสดงออกทางคณิตศาสตร์$(...) $((...))เชลล์บางตัวแนะนำบริบทเพิ่มเติมเช่นkshชุดย่อยการแทนที่คำสั่งx=${ echo foo; echo bar;}(ซึ่งแตกต่างจากมาตรฐาน$(...)โดยไม่เรียกใช้คำสั่งในเชลล์ย่อย)
chepner

@chepner คุณสนใจที่จะคำนึงถึงความแตกต่างของความคิดเห็นระหว่าง Issac และ Michael Homer หรือไม่? คำตอบของพวกเขาขัดแย้งกันอย่างชัดเจน
Harold Fischer

1
ฉันเห็นด้วยกับการตีความของ Michael Homer; เชลล์ไม่เริ่มกังวลเกี่ยวกับการขยายจนกระทั่งหลังจากการแยกวิเคราะห์เสร็จสมบูรณ์ดังนั้นในคำเดียวab$ไม่มีการติดตามอักขระ$ไม่ว่าจะเป็น "ตาม" โดยอักขระ null ในสตริงอินพุตดั้งเดิมหรือช่องว่างในกรณี ชอบecho ab$ foo; ช่องว่างต้นฉบับที่ไม่ได้อ้างอิงได้รับการยอมรับและถูกทิ้งหลังจากการแยกวิเคราะห์
chepner

คำตอบ:


10

$ไม่มีความหมายพิเศษด้วยตัวเอง (ลองecho $) เฉพาะเมื่อรวมกับอักขระอื่น ๆ หลังจากนั้นและสร้างส่วนขยายเช่น$var(หรือ${var})$(util) )$((1+2)) ,

การ$ได้รับความหมาย "พิเศษ" ของมันเป็นการกำหนดส่วนขยายในมาตรฐาน POSIX ภายใต้การรับรู้โทเค็น :

ถ้าตัวอักษรตัวปัจจุบันเป็น unquoted $หรือ`เปลือกจะระบุจุดเริ่มต้นของผู้สมัครใด ๆ สำหรับการขยายตัวพารามิเตอร์แทนคำสั่งหรือการขยายตัวทางคณิตศาสตร์จากเบื้องต้นลำดับตัวอักษร unquoted ของพวกเขา: $หรือ${, $(หรือ`และ$((ตามลำดับ เชลล์จะอ่านอินพุตที่เพียงพอเพื่อกำหนดจุดสิ้นสุดของยูนิตที่จะขยาย ( ดังอธิบายในส่วนที่อ้างถึง) ในขณะที่ประมวลผลตัวอักษรหากพบว่ามีอินสแตนซ์ของการขยายหรือการอ้างอิงซ้อนกันภายในการทดแทนเชลล์จะประมวลผลอักขระเหล่านั้นซ้ำในลักษณะที่ระบุไว้สำหรับโครงสร้างที่พบ อักขระที่พบตั้งแต่เริ่มต้นของการทดแทนจนถึงจุดสิ้นสุดทำให้การเรียกซ้ำใด ๆ ที่จำเป็นในการรับรู้การสร้างที่ฝังตัวจะต้องไม่มีการแก้ไขในโทเค็นผลลัพธ์รวมถึงตัวดำเนินการหรือเครื่องหมายคำพูดแบบฝังหรือล้อมรอบ โทเค็นจะไม่ถูกคั่นด้วยการสิ้นสุดของการทดแทน

ดังนั้นหาก$ไม่ได้สร้างส่วนขยายกฎการแยกวิเคราะห์อื่น ๆ จะมีผล:

หากตัวละครก่อนหน้าเป็นส่วนหนึ่งของคำตัวอักษรปัจจุบันจะถูกผนวกเข้ากับคำนั้น

ที่ครอบคลุมab$สตริงของคุณ

ในกรณีของโดดเดี่ยว$("คำใหม่" จะเป็นของ$ตัวเอง):

อักขระปัจจุบันถูกใช้เป็นจุดเริ่มต้นของคำใหม่

ความหมายของคำที่สร้างขึ้นมี$ที่ไม่ได้เป็นขยายตัวมาตรฐานที่กำหนดไว้อย่างชัดเจนว่าไม่เกี่ยวกับบุคคลโดย POSIX

นอกจากนี้โปรดทราบว่า$เป็นอักขระตัวสุดท้ายใน$$แต่สิ่งนี้ก็เกิดขึ้นเป็นตัวแปรที่เก็บ PID ของเชลล์ปัจจุบัน ในbash, !$อาจก่อให้เกิดการขยายตัวของประวัติศาสตร์ (อาร์กิวเมนต์สุดท้าย af คำสั่งก่อนหน้า) โดยทั่วไปแล้วไม่$ไม่ได้โดยไม่มีความหมายในตอนท้ายของคำที่ไม่มีคำพูด แต่ในตอนท้ายของคำอย่างน้อยที่สุดก็ไม่ได้หมายถึงการขยายมาตรฐาน


7

ทั้งนี้ขึ้นอยู่กับสถานการณ์ที่แน่นอนสิ่งนี้อาจไม่ระบุอย่างชัดเจน (ดังนั้นการนำไปปฏิบัติอาจทำได้ตามที่ต้องการ) หรือจำเป็นต้องเกิดขึ้นตามที่คุณสังเกตเห็น ในสถานการณ์ที่แน่นอนของคุณecho ab$, POSIX เอกสารส่งออก "AB $" ที่คุณสังเกตเห็นและมันไม่ได้เป็นที่ไม่ได้ระบุ บทสรุปอย่างรวดเร็วของทุกกรณีที่แตกต่างกันคือในตอนท้าย

มีองค์ประกอบอยู่สองประการด้วยกันคือการทำให้เป็นคำแรกจากนั้นจึงตีความคำเหล่านั้น


Tokenisation

POSIX tokenisation ต้องว่า$ที่ไม่ได้เป็นจุดเริ่มต้นของที่ถูกต้องการขยายตัวพารามิเตอร์ , แทนคำสั่งหรือเปลี่ยนตัวคณิตศาสตร์ที่จะได้รับการพิจารณาเป็นส่วนหนึ่งที่แท้จริงของWORDความเป็นโทเค็นการสร้าง เพราะนี่คือกฎที่ 5 ( "ถ้าตัวละครปัจจุบันเป็น unquoted $หรือ`เปลือกจะระบุจุดเริ่มต้นของผู้สมัครใด ๆ สำหรับการขยายตัวพารามิเตอร์แทนคำสั่งหรือการขยายตัวทางคณิตศาสตร์จากเบื้องต้นลำดับตัวอักษร unquoted ของพวกเขา$หรือ${, $(หรือ`และ$((ตามลำดับ" ) ใช้ไม่ได้เนื่องจากไม่มีส่วนขยายใด ๆ การขยายพารามิเตอร์ต้องการชื่อที่ถูกต้องเพื่อปรากฏที่นั่นและชื่อที่ว่างเปล่าไม่ถูกต้อง

เนื่องจากกฎนี้ใช้ไม่ได้เราจึงดำเนินการต่อไปจนกว่าเราจะพบกฎที่ใช้ ผู้สมัครทั้งสองคือ # 8 ("หากอักขระก่อนหน้าเป็นส่วนหนึ่งของคำอักขระปัจจุบันจะถูกต่อท้ายคำนั้น") และ # 10 ("อักขระปัจจุบันถูกใช้เป็นจุดเริ่มต้นของคำใหม่") ซึ่งใช้กับecho a$และecho $ตามลำดับ

นอกจากนี้ยังมีกรณีที่สามของแบบฟอร์มecho a$+bที่ตกผ่านรอยแตกเดียวกันเนื่องจาก+ไม่ใช่ชื่อของพารามิเตอร์พิเศษ อันนี้เราจะกลับไปทีหลังเพราะมันก่อให้เกิดส่วนต่าง ๆ ของกฎ

สเปคจึงต้อง$ให้ถือว่าเป็นส่วนหนึ่งของคำ syntactically และจากนั้นจะสามารถดำเนินการต่อไปในภายหลัง


การขยายคำ

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

มีการระบุว่า :

หากไม่มีเครื่องหมายอัญประกาศ '$' ตามด้วยอักขระที่ไม่ใช่ตัวใดตัวหนึ่งต่อไปนี้:

  • อักขระตัวเลข
  • ชื่อของหนึ่งในพารามิเตอร์พิเศษ (ดูพารามิเตอร์พิเศษ )
  • อักขระตัวแรกที่ถูกต้องของชื่อตัวแปร
  • A <left-curly-bracket>('{')
  • <left-parenthesis>

ผลลัพธ์ไม่ได้ระบุ

"ไม่ระบุ" เป็นคำเฉพาะที่นี่หมายความว่า

  1. เชลล์ที่สอดคล้องกันสามารถเลือกพฤติกรรมใด ๆ ในกรณีนี้
  2. แอปพลิเคชันที่สอดคล้องไม่สามารถพึ่งพาพฤติกรรมใด ๆ

ในตัวอย่างของecho ab$การ$ ไม่ปฏิบัติตามโดยการใด ๆของตัวละครเพื่อให้กฎนี้ใช้ไม่ได้ผลและไม่ได้ระบุไม่ได้เรียก มีเพียงการขยายตัวไม่เข้าฝันโดย$ดังนั้นจึงมีอยู่จริงและพิมพ์ออกมา

ที่มันจะecho a$+bนำไปใช้ในกรณีที่สามของเราจากเบื้องบน ที่นี่$มีผู้ติดตาม+ซึ่งเป็นตัวเลขที่ไม่พารามิเตอร์พิเศษ ( @, *, #, ?, -, $, !หรือ0) เริ่มต้นของตัวแปรชื่อ (ขีดหรือตัวอักษรจากชุดตัวอักษรแบบพกพา ) หรือหนึ่งในวงเล็บ ในกรณีนี้พฤติกรรมที่ไม่ระบุรายละเอียด: เปลือกสอดคล้องจะได้รับอนุญาตในการคิดค้นพารามิเตอร์พิเศษที่เรียกว่า+จะขยายและแอปพลิเคสอดคล้องไม่ควรคิดว่าเปลือกไม่ เชลล์สามารถทำอะไรก็ได้ที่มันชอบเช่นกันรวมถึงการรายงานข้อผิดพลาด

ตัวอย่างเช่น zsh รวมถึงในโหมด POSIX ตีความ$+bว่า "เป็นbชุดตัวแปร"และทดแทน 1 หรือ 0 ทั้งที่แทน ในทำนองเดียวกันมันมีส่วนขยายและ~ =นี่คือพฤติกรรมที่สอดคล้อง

echo "a$ b"สถานที่แห่งนี้จะเกิดขึ้นก็คือ อีกครั้งเชลล์ได้รับอนุญาตให้ทำตามที่ต้องการและคุณในฐานะผู้เขียนสคริปต์ควรหลีกเลี่ยง$ถ้าคุณต้องการผลลัพธ์ที่แท้จริง ถ้าคุณทำไม่ได้มันอาจใช้งานได้ แต่คุณไม่สามารถไว้ใจได้ นี่คือตัวอักษรที่แน่นอนของข้อกำหนด แต่ฉันไม่คิดว่าการเรียงลำดับแบบนี้มีจุดมุ่งหมายหรือพิจารณา


สรุป

  • echo ab$: เอาต์พุตตัวอักษรที่ระบุอย่างเต็มที่
  • echo a$ b: เอาต์พุตตัวอักษรที่ระบุอย่างเต็มที่
  • echo a$ b$: เอาต์พุตตัวอักษรที่ระบุอย่างเต็มที่
  • echo a$b: การขยายตัวของพารามิเตอร์bที่ระบุไว้อย่างสมบูรณ์
  • echo a$-b: การขยายตัวของพารามิเตอร์พิเศษ-ที่ระบุไว้อย่างเต็มที่
  • echo a$+b: พฤติกรรมที่ไม่ระบุ
  • echo "a$ b": พฤติกรรมที่ไม่ระบุ

สำหรับ$ท้ายคำคุณได้รับอนุญาตให้พึ่งพาพฤติกรรมและต้องได้รับการปฏิบัติอย่างแท้จริงและส่งต่อไปยังechoคำสั่งซึ่งเป็นส่วนหนึ่งของการโต้แย้ง นั่นคือข้อกำหนดที่สอดคล้องกับเชลล์


ความคิดเห็นไม่ได้มีไว้สำหรับการอภิปรายเพิ่มเติม การสนทนานี้ได้รับการย้ายไปแชท
terdon

@MichaelHomer จะecho $เป็นตัวอักษรและระบุอย่างเต็มที่หรือไม่
แฮโรลด์ฟิสเชอร์

@HaroldFischer ใช่
Michael Homer

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