หยุดการขยายอักขระตัวแทนเชลล์หรือไม่


91

มีวิธีใดบ้างที่โปรแกรมบรรทัดคำสั่งคอมไพล์จะบอก bash หรือ csh ว่าไม่ต้องการให้อักขระตัวแทนใด ๆ ในพารามิเตอร์ขยาย

ตัวอย่างเช่นอาจต้องการคำสั่งเชลล์เช่น:

foo *

เพื่อส่งคืนค่า ASCII ที่เป็นตัวเลขของอักขระนั้น

คำตอบ:


122

ไม่การขยายเกิดขึ้นก่อนที่คำสั่งจะรันจริง
คุณสามารถปิดใช้งาน glob ก่อนที่จะเรียกใช้คำสั่งหรือโดยอ้างถึงดาว

$ # quote it
$ foo '*'

$ # or escape it
$ foo \*

$ # or disable the glob (noglob)
$ set -f
$ foo *

$ # alternative to set -f
$ set -o noglob
$ # undo it by 
$ set +o noglob

3
นอกจากนี้หากไม่มีอะไรจะขยายก็ไม่มีการขยาย คือมีที่ว่างเปล่าpwd, echo *เป็นเพียง*
sam boosalis

7
@sam สิ่งนี้ขึ้นอยู่กับวิธีตั้งค่าตัวเลือกของคุณ จาก tldp: "หากไม่พบชื่อไฟล์ที่ตรงกันและnullglobปิดใช้งานตัวเลือกเชลล์คำนั้นจะไม่เปลี่ยนแปลงหากnullglobตั้งค่าตัวเลือกและไม่พบคำที่ตรงกัน
Chris Middleton

ขอบคุณฉันควรมีคุณสมบัติที่เป็นเพียงจากการสังเกตไม่ได้มาจากความเข้าใจใด ๆ
sam boosalis

@ c00kiemon5ter วิธีการยกเลิกset -f? มันคือunset -fอะไร?
Nam G VU

1
@NamGVUset +f
Yngvar Kristiansen

63

แม้ว่าจะเป็นความจริง แต่คำสั่งเองก็ไม่สามารถปิด globbing ได้ แต่ก็เป็นไปได้ที่ผู้ใช้จะบอก Unix shell ไม่ให้ glob คำสั่งเฉพาะ โดยปกติจะทำได้โดยการแก้ไขไฟล์คอนฟิกูเรชันของเชลล์ สมมติว่าfooสามารถพบคำสั่งได้ตามเส้นทางคำสั่งจำเป็นต้องเพิ่มสิ่งต่อไปนี้ในไฟล์คอนฟิกูเรชันที่เหมาะสม:

สำหรับเปลือก sh, bash และ ksh:

alias foo='set -f;foo';foo(){ command foo "$@";set +f;}

สำหรับเชลล์ csh และ tcsh:

alias foo 'set noglob;\foo \!*;unset noglob'

สำหรับ zsh เชลล์:

alias foo='noglob foo'

ไม่จำเป็นต้องใช้พา ธ คำสั่ง พูดว่าคำสั่ง foo ถูกเก็บไว้ในไดเร็กทอรี ~ / bin จากนั้นด้านบนจะกลายเป็น:

สำหรับเปลือก sh, bash และ ksh:

alias foo='set -f;foo';foo(){ ~/bin/foo "$@";set +f;}

สำหรับเชลล์ csh และ tcsh:

alias foo 'set noglob;$home/bin/foo \!*;unset noglob'

สำหรับ zsh เชลล์:

alias foo='noglob ~/bin/foo'

ทั้งหมดข้างต้นได้รับการทดสอบโดยใช้ OSX 10.9.2 ของ Apple หมายเหตุ: เมื่อคัดลอกโค้ดด้านบนโปรดระมัดระวังการลบช่องว่างใด ๆ อาจมีความสำคัญ

อัปเดต:

ผู้ใช้geiraได้ชี้ให้เห็นว่าในกรณีของ bash shell

alias foo='set -f;foo';foo(){ ~/bin/foo "$@";set +f;}

สามารถแทนที่ด้วย

reset_expansion(){ CMD="$1";shift;$CMD "$@";set +f;}
alias foo='set -f;reset_expansion ~/bin/foo'

ซึ่งไม่จำเป็นต้องใช้ฟังก์ชัน foo

บางเว็บไซต์ที่ใช้สร้างเอกสารนี้:


3
นี่ควรเป็นคำตอบที่ได้รับการยอมรับเนื่องจากพิสูจน์ได้ว่าเป็นไปได้ที่จะทำในสิ่งที่ OP ต้องการ สำหรับวิธีการที่ดียิ่งขึ้นในการทุบตีลิงก์นี้จะบันทึกตัวเลือกต่างๆ: blog.edwards-research.com/2011/05/preventing-globbing
geira

@geira: บางครั้งอาจมีการยอมรับคำตอบก่อนที่จะมีการโพสต์คำตอบที่ดีกว่า ฉันเชื่อว่านี่อาจเป็นหนึ่งในกรณีเหล่านั้น ฉันยังเชื่อว่าคำตอบที่เป็นประโยชน์ที่สุดของผู้ใช้จะจบลงก่อน หมายเหตุ: ฉันเพิ่มข้อมูลของคุณในคำตอบของฉัน
David Anderson

@geira OP ต้องการให้โปรแกรมที่คอมไพล์สื่อสารกับเชลล์ การตอบว่าเป็นไปได้ที่จะกำหนดค่าเชลล์ให้ทำงานตามที่ต้องการโดยใช้คำสั่งทีละคำสั่งเป็นคำตอบที่มีประโยชน์และตัวฉันเองก็ยอมรับคำตอบนี้ แต่ฉันเห็นว่ามีช่องว่างที่จะไม่เห็นด้วยว่ามันตรงประเด็นทั้งหมดหรือไม่
Charles Duffy

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

@tripleee: มีช่วงหนึ่งที่ผู้คนคาดหวังว่ารีเลย์และท่อสุญญากาศ คาดว่าเป็นรูเจาะในการ์ดกระดาษแข็งและเทปกระดาษ ผู้คนถือกฎสไลด์แทนเครื่องคิดเลขและโทรศัพท์ ฉันคิดว่าสำหรับคุณสิ่งนี้น่าจะเป็นที่ต้องการ ฉันไม่ได้สนใจมากสำหรับช่วงเวลานั้น ฉันสนุกกับการได้เห็นสิ่งต่อไป
David Anderson

8

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

   set -o noglob

จะปิดการขยายในเชลล์ที่เรียกใช้ แต่คุณต้องทำก่อนที่จะเรียกใช้โปรแกรมของคุณ

อีกทางเลือกหนึ่งคือการอ้างข้อโต้แย้งของคุณเช่น

foo "*"

4
setopt ดูเหมือนจะเป็นคำสั่งเฉพาะ zsh ดังที่ผู้โพสต์คนอื่นกล่าวไว้สำหรับ bash คุณใช้set -o noglobเพื่อปิดใช้งานการขยายสัญลักษณ์แทน
Wirawan Purwanto

ตอนนี้แก้ไขแล้ว. ขอบคุณ
Brian Agnew

1

ระวัง: หากไม่มีชื่อที่ตรงกับมาสก์ bash จะส่งอาร์กิวเมนต์ตามที่เป็นอยู่โดยไม่ต้องขยาย!

Proof (pa.py เป็นสคริปต์ที่ง่ายมากซึ่งเพียงแค่พิมพ์อาร์กิวเมนต์):

 $ ls
f1.cc  f2.cc  pa.py
 $ ./pa.py *.cc
['./pa.py', 'f1.cc', 'f2.cc']
 $ ./pa.py *.cpp
['./pa.py', '*.cpp']

3
ไม่เสมอ. set -o nullglobหรือshopt -s failglobและพฤติกรรมนี้จะเปลี่ยนไป (ในสองวิธีที่แตกต่างกันมาก)
Charles Duffy
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.