ฉันรู้ว่าอาจมีการถามก่อนหน้านี้ แต่ฉันไม่พบมันด้วย Google
ป.ร. ให้ไว้
- เคอร์เนล Linux
- ไม่มีการกำหนดค่าที่เปลี่ยนแปลง $ HOME
- ทุบตี
จะ~ == $HOMEเป็นจริงหรือ
echo "~" echo "$HOME"
~ $HOME: P
ฉันรู้ว่าอาจมีการถามก่อนหน้านี้ แต่ฉันไม่พบมันด้วย Google
ป.ร. ให้ไว้
จะ~ == $HOMEเป็นจริงหรือ
echo "~" echo "$HOME"
~ $HOME: P
คำตอบ:
สิ่งสำคัญที่ต้องเข้าใจคือ~การขยายเป็นคุณลักษณะของเชลล์ (ของเชลล์บางตัว) มันไม่ใช่ตัวอักษรเวทมนต์มากกว่าที่จะหมายถึงโฮมไดเร็กตอรี่ที่คุณใช้
มันถูกขยาย (โดยเชลล์ซึ่งเป็นแอ็พพลิเคชันที่ใช้ตีความบรรทัดคำสั่ง) เช่น$varถูกขยายเป็นค่าภายใต้เงื่อนไขบางอย่างเมื่อใช้ในบรรทัดคำสั่งเชลล์ก่อนที่คำสั่งจะถูกดำเนินการ
คุณสมบัติดังกล่าวปรากฏตัวครั้งแรกใน C-shell ในช่วงปลายทศวรรษ 1970 (บอร์นเชลล์ไม่ได้มีหรือไม่ได้เป็นรุ่นก่อนหน้าของ ธ อมป์สันเชลล์) ถูกเพิ่มเข้ามาใน Korn เชลล์ (เชลล์ใหม่ที่สร้างขึ้นบนเชลล์ Bourne ใน 80) ในที่สุดมันก็มาตรฐานโดย POSIX และตอนนี้ที่มีอยู่ในเปลือกหอยส่วนใหญ่รวมทั้งคนที่ไม่ใช่ POSIX fishเช่น
เนื่องจากมันมีการใช้งานอย่างแพร่หลายในเชลล์แอปพลิเคชันที่ไม่ใช่เชลล์บางตัวจึงรับรู้ได้ว่ามันหมายถึงโฮมไดเร็กตอรี่ นั่นคือกรณีที่มีการใช้งานจำนวนมากในแฟ้มการกำหนดค่าของพวกเขาหรือพวกเขาเองบรรทัดคำสั่ง ( mutt, slrn, vim... )
bashโดยเฉพาะ (ซึ่งเป็นเชลล์ของโครงการ GNU และใช้กันอย่างแพร่หลายในหลายระบบปฏิบัติการบน Linux) เมื่อมีการเรียกใช้shนั้นส่วนใหญ่จะเป็นไปตามกฎ POSIXเกี่ยวกับ~การขยายตัวและในพื้นที่ที่ไม่ได้ระบุไว้โดย POSIX พฤติกรรมส่วนใหญ่จะเหมือนกับ Korn เชลล์ ซึ่งมันเป็นส่วนโคลน)
ขณะที่$varถูกขยายในสถานที่ส่วนใหญ่ (ยกเว้นในเครื่องหมายคำพูดเดียว) ~การขยายการคิดภายหลังจะขยายในเงื่อนไขเฉพาะบางอย่างเท่านั้น
มันจะขยายตัวเมื่ออาร์กิวเมนต์ของตัวเองในรายการบริบทในบริบทที่คาดว่าสตริง
นี่คือตัวอย่างบางส่วนของที่ขยายในbash:
cmd arg ~ other argvar=~var=x:~:x(ต้องการโดย POSIX ใช้สำหรับตัวแปรเช่นPATH, MANPATH... )for i in ~[[ ~ = text ]][[ text = ~ ]](การขยายตัวของ~การถ่ายเป็นรูปแบบใน AT&T kshแต่ไม่ใช่bashตั้งแต่ 4.0)case ~ in ~) ...${var#~} (แม้ว่าจะไม่ได้อยู่ในกระสุนอื่น ๆ )cmd foo=~(แม้ว่าจะไม่ใช่เมื่อถูกเรียกเป็นshและเฉพาะเมื่อสิ่งที่อยู่ทางด้านซ้ายของ=มีรูปร่างเหมือนbashชื่อตัวแปรที่ไม่ได้กล่าวถึง)cmd ~/x (ต้องการโดย POSIX อย่างเห็นได้ชัด)cmd ~:x(แต่ไม่ใช่x:~:xหรือx-~-x)a[~]=foo; echo "${a[~]} $((a[~]))" (ไม่ได้อยู่ในเปลือกหอยอื่น ๆ )นี่คือตัวอย่างบางส่วนที่ไม่ได้ขยาย:
echo "~" '~'echo ~@ ~~(โปรดทราบว่า~uมีไว้เพื่อขยายไปยังโฮมไดเร็กตอรี่ของผู้ใช้u)echo @~(( HOME == ~ )), $(( var + ~ ))extglob: case $var in @(~|other))...(แม้ว่าcase $var in ~|other)จะตกลง)./configure --prefix=~(เนื่องจาก--prefixไม่ใช่ชื่อตัวแปรที่ถูกต้อง)cmd "foo"=~(ในbashเพราะคำพูด)sh: export "foo"=~, env JAVA_HOME=~ cmd...สำหรับสิ่งที่มันขยายเป็น: ~เพียงอย่างเดียวขยายไปยังเนื้อหาของHOMEตัวแปรหรือเมื่อไม่ได้ตั้งค่าไว้ที่โฮมไดเร็กทอรีของผู้ใช้ปัจจุบันในฐานข้อมูลบัญชี (เป็นส่วนขยายเนื่องจาก POSIX ทำให้พฤติกรรมนั้นไม่ได้กำหนดไว้)
ควรสังเกตว่าใน ksh88 และbashเวอร์ชันก่อนหน้า 4.0 การขยายตัวหนอนจะได้รับการทำให้เป็นวงกลม(การสร้างชื่อไฟล์) ในบริบทรายการ:
$ bash -c 'echo "$HOME"'
/home/***stephane***
$ bash -c 'echo ~'
/home/***stephane*** /home/stephane
$ bash -c 'echo "~"'
~
ที่ไม่ควรมีปัญหาในกรณีปกติ
โปรดทราบว่าเนื่องจากมีการขยายคำเตือนเดียวกันจะมีผลกับการขยายรูปแบบอื่น ๆ
cd ~
ไม่ทำงานหาก$HOMEเริ่มต้นด้วย-หรือมี..ส่วนประกอบ ดังนั้นแม้ว่าจะไม่สร้างความแตกต่างใด ๆ เลย แต่การพูดอย่างเคร่งครัดควรเขียนว่า:
cd -P -- ~
หรือแม้กระทั่ง:
case ~ in
(/*) cd -P ~;;
(*) d=~; cd -P "./$d";;
esac
(เพื่อครอบคลุมค่าที่$HOMEต้องการ-, +2... ) หรือเพียงแค่:
cd
(ตามที่cdนำคุณไปสู่โฮมไดเร็กตอรี่โดยไม่มีอาร์กิวเมนต์)
กระสุนอื่น ๆ มี~การขยายเพิ่มเติมขั้นสูง ตัวอย่างเช่นในzshเรามี:
~4, ~-, ~-2(ด้วยความสมบูรณ์) ที่ใช้ในการขยายไดเรกทอรีในกองไดเรกทอรีของคุณ (สถานที่ที่คุณเคยcdไปมาก่อน)~somethingจะขยายตัวอย่างไรในรุ่นใด ๆ ของทุบตีในระบบใด ๆ ใช่ ~เป็นคำที่ตัวเองถูกกำหนดให้ขยายไปยัง:
ค่าของ $ HOME
ดังนั้นมันจะเหมือนกับสิ่งที่$HOMEอยู่ในเชลล์ปัจจุบันเสมอ มีการขยายตัวหนอนอื่น ๆ อีกหลายอย่างเช่น~userสำหรับuserโฮมไดเร็กตอรี่~ของ, แต่สิ่งที่ไม่ได้กล่าวถึงในตัวมันจะขยายออกไป"$HOME"เสมอ
โปรดทราบว่าพฤติกรรมของ~และ$HOMEสามารถแตกต่างกันได้ในบางกรณี: โดยเฉพาะถ้า$HOMEมีช่องว่าง (หรืออักขระIFSอื่น ๆ) จากนั้น$HOME(ไม่พูดถึง) จะขยายออกเป็นหลายคำในขณะที่~เป็นคำเดียวเสมอ ~ขยายเท่ากับ"$HOME"(ที่ยกมา)
สำหรับคำถามเฉพาะของคุณ:
[[ $HOME == ~ ]]
เป็นจริงเสมอเพราะ[[ ยับยั้งการแยกคำ [[ ~ == $HOME ]อาจจะไม่ได้ถ้าHOMEมีตัวอักษรที่ตรงกับรูปแบบในมัน แต่[[ ~ == "$HOME" ]](เช่นที่ยกมา"$HOME") เป็นจริงเสมอ การใช้ภายในวงเล็บปีกกาเดียวอาจเป็นข้อผิดพลาดทางไวยากรณ์สำหรับค่าของการHOMEเว้นวรรคหรืออักขระพิเศษ สำหรับการกำหนดค่าโฮมไดเรกทอรีที่สมเหตุสมผลใด ๆ~และ"$HOME"เหมือนกันและเปรียบเทียบเท่ากัน
Stéphane Chazelas ได้บันทึกกรณีในความคิดเห็นที่~และ$HOMEให้ค่าที่แตกต่าง: ถ้าคุณunset HOMEแล้วเมื่อคุณใช้~Bash จะโทรgetpwuidเพื่ออ่านค่าออกจากฐานข้อมูลรหัสผ่าน กรณีนี้ไม่รวมอยู่ในเงื่อนไขที่คุณไม่มีการเปลี่ยนแปลงการกำหนดค่า$HOMEแต่ฉันจะพูดถึงเรื่องนี้เพื่อความสมบูรณ์
/bin/sh bashฉันไม่แน่ใจว่าshข้อมูลจำเพาะของPosix บอกเกี่ยวกับ~
~ระบุ POSIX ~ไม่ได้อยู่ใน Thomson หรือ Bourne shell (ซึ่งในเวลานั้นมีให้ในรูป/bin/sh) มันไม่ได้อยู่ในrcหรืออนุพันธ์ (ที่จะใช้อย่างอื่น)
bashหากHOMEไม่ได้ตั้งค่า~จะขยายไปยังโฮมไดเร็กทอรีของผู้ใช้จากฐานข้อมูล passwd เพื่อให้เป็นกรณีที่ไม่อาจขยายไปยังค่าของ~ $HOME
bashก่อนที่ bash4 จะใช้ในการทำการวนรอบตามการขยายตัวของตัวหนอน (ลองHOME='/*' bash -c 'echo /*') ดังนั้นHOME=/*; [ "$HOME" = ~ ]จะกลับข้อผิดพลาดที่นั่น
get_current_user_infoซึ่งใช้getpwuidบนแพลตฟอร์มทั้งหมด แต่ Tandem
~จะเทียบเท่ากับ$HOMEในสภาพแวดล้อม POSIX ใด ๆ ; แต่ฉันอาจจะผิด