ทำไมเครื่องหมายตัวหนอน (~) ไม่ขยายภายในเครื่องหมายคำพูดคู่


54

ตามคำตอบนี้และความเข้าใจของฉันเอง tilde ขยายไปยังโฮมไดเร็กตอรี่:

$ echo ~
/home/braiam

ตอนนี้เมื่อใดก็ตามที่ฉันต้องการให้ส่วนขยายของเชลล์ทำงานเช่นใช้ชื่อตัวแปรเช่น$FOOนี้และไม่ทำลายอักขระที่ไม่คาดคิดเนื่องจากช่องว่างและอื่น ๆ เราควรใช้เครื่องหมายคำพูดคู่":

$ FOO="some string with spaces"
$ BAR="echo $FOO"
$ echo $BAR
echo some string with spaces

ทำไมการขยายตัวนี้จึงใช้งานไม่ได้กับเครื่องหมายตัวหนอน

$ echo ~/some/path
/home/braiam/some/path
$ echo "~/some/path"
~/some/path


3
นอกจากนี้โปรดทราบว่าสิ่งนี้มีความไม่สอดคล้องกันเมื่อจัดเตรียมอาร์กิวเมนต์ของโปรแกรมบนบรรทัดคำสั่งที่บนอาร์กิวเมนต์ของคำสั่ง--path ~/myfileจะขยายออก แต่--path=~/myfileไม่มี
Ángel

ที่เกี่ยวข้อง: เท่ากับ $ HOME เสมอ
Stéphane Chazelas


มีการเปลี่ยนแปลงในรูปแบบนี้เป็นunix.stackexchange.com/questions/279565
JdeBP

คำตอบ:


45

เหตุผลเนื่องจากในเครื่องหมายคำพูดคู่ตัวหนอน~ไม่มีความหมายพิเศษจึงถือว่าเป็นตัวอักษร

POSIX กำหนดDouble-Quotesเป็น:

อักขระที่ล้อมรอบในเครื่องหมายคำพูดคู่ ("") จะต้องรักษาคุณค่าที่แท้จริงของตัวละครทั้งหมดภายในเครื่องหมายคำพูดคู่ยกเว้นเครื่องหมายดอลลาร์ตัวอักษร backquote และ backslash

...

แอปพลิเคชันจะต้องตรวจสอบให้แน่ใจว่ามีเครื่องหมายคำพูดคู่อยู่ข้างหน้าด้วยเครื่องหมายแบ็กสแลชที่จะรวมอยู่ในเครื่องหมายคำพูดคู่ พารามิเตอร์ '@' มีความหมายพิเศษภายในเครื่องหมายคำพูดคู่

ยกเว้น$, `, \และ@ตัวละครอื่น ๆ จะถือว่าเป็นตัวอักษรให้อยู่ในเครื่องหมาย


9
$HOMEซึ่งในกรณีนี้ผมคิดว่าคุณควรจะใช้
เซท

11
หรือคุณไม่สามารถพูด~เช่นls -l ~/"My Documents"
Andrew Medico

สิ่งนี้ไม่ง่ายมาก เหตุผลที่พวกเขาเลือกทำเช่นนี้คืออะไร? (คำตอบนี้ไม่ได้ให้เหตุผล แต่เพียงชี้ไปที่มาตรฐาน แต่สันนิษฐานว่ามาตรฐานเขียนด้วยวิธีนั้นด้วยเหตุผล )
iconoclast

1
@iconoclast หากคุณต้องการ "ทำไมพวกเขาถึงใช้วิธีนี้" อ่านคำตอบของStephaneแทน
Braiam

2
ดังนั้น @iconoclast ทำไมท้องฟ้าถึงเป็นสีฟ้า? :) :) :)
Jesse Chisholm

32

การขยายตัวตัวหนอนถูกกำหนดโดย POSIX เป็น:

A "ตัวหนอนคำนำหน้า" ประกอบด้วยunquoted <หนอน> ตัวอักษรที่จุดเริ่มต้นของคำตามด้วยทุกตัวอักษรก่อนหน้าแรก unquoted <เฉือน> ในคำหรือตัวอักษรทั้งหมดที่อยู่ในคำว่าถ้าไม่มี < เฉือน> ในการมอบหมายสามารถใช้คำนำหน้า tilde หลายคำได้: [... ] ตาม <equals-sign> ของการมอบหมายต่อจาก <colon> ที่ไม่มีเครื่องหมายหรือทั้งสองอย่าง [... ] หากไม่มีตัวอักษรใด ๆ ในเครื่องหมายคำนำหน้าตัวหนอน tilde ตัวอักษรในเครื่องหมายคำนำหน้าตัวหนอนหลังเครื่องหมาย <tilde> จะถือว่าเป็นชื่อล็อกอินที่เป็นไปได้จากฐานข้อมูลผู้ใช้ [... ] หากชื่อล็อกอินเป็นโมฆะ (นั่นคือคำนำหน้าตัวหนอนมีเพียงตัวหนอนเท่านั้น) ตัวหนอนหน้าตัวหนอนจะถูกแทนที่ด้วยค่าของตัวแปร HOME หากหน้าแรกไม่ได้ตั้งค่าผลลัพธ์จะไม่ถูกระบุ [ ... ]

ดังนั้นคำตอบที่สั้นที่สุดคือ "เพราะมันถูกกำหนดไว้อย่างนั้น": การอ้างอิงอักขระใด ๆ ในคำนำหน้ารวมถึงการ~หยุดการขยายตัว

นอกจากนี้ยังกำหนดการขยายตัวเช่นเดียวกับที่เกิดขึ้นในคำเดียวดังนั้นการอ้างจะไม่จำเป็น:

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

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

$ cat ~/"file name with spaces"

ในวงกว้าง "ทำไม": เนื่องจากไม่มีการใช้เป็นไปได้สำหรับการแยกคำ~ที่ควรจะเป็นพฤติกรรมเริ่มต้นมากกว่าที่จะต้องมีการอ้าง เพราะไม่จำเป็นต้องพูดมันการให้~ความหมายพิเศษในเครื่องหมายคำพูดนั้นจะเป็นความยุ่งยากที่ไม่จำเป็น และแน่นอนด้วยเหตุผลทางประวัติศาสตร์หมายความว่าไม่สามารถเปลี่ยนแปลงได้ในขณะนี้แม้ว่าจะเป็นที่น่าพอใจก็ตาม


ตามคู่มือทุบตีนี้การขยายตัวหนอนเกิดขึ้นก่อนที่จะแยกช่องว่าง มีวิธีที่จะทำการขยายตัวหนอนอย่างปลอดภัยแม้ว่าไดเรกทอรีบ้านของคุณมีช่องว่างหรือไม่ ""ปกติแน่นอนคุณต้องการทำเรียงลำดับของสิ่งนี้กับ
Lucretiel

การขยายตัวเป็นคำเดียว ดูข้อความที่ยกมาสองในคำตอบ
Michael Homer

23

~ มีต้นกำเนิดใน C-shell นานก่อนที่จะถูกเพิ่มเข้ากับ Korn เชลล์และเพิ่มในภายหลังไปยังข้อมูลจำเพาะเชลล์ POSIX

ใน C-shell ~เป็นตัวดำเนินการแบบวงกลม (ขยายตามรูทีนตัวเดียวกับตัวขยาย*.txtตัวอย่าง) ดังนั้นเช่นเดียวกับส่วนที่เหลือของวงกลมที่ไม่ได้ทำในเครื่องหมายคำพูดคู่


11

ขณะนี้ไม่ได้คำตอบว่าทำไมมันได้รับการออกแบบวิธีการที่คุณใช้$HOMEแทนถ้าคุณต้องทดแทนตั้งแต่ที่เป็นหลักสิ่งที่~ไม่

$ echo "$HOME/some/path"
/home/braiam/some/path

6
สิ่งนี้ใช้ไม่ได้กับ~otheruser
Johannes Kuhn

2
จริง แต่คุณสามารถทำ: พวกเขา = ~ otheruser แล้วใช้ "$ พวกเขา / บาง / เส้นทาง"
ผสมผสาน

1
วิธีแก้ปัญหาสำหรับการ~otheruserแสดงให้เห็นถึงความคิดที่ไม่ดีที่จะปฏิบัติ~แตกต่างจากตัวแปรและสิ่งอื่น ๆ ที่ถูกขยายในเครื่องหมายคำพูดคู่
iconoclast
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.