ขั้นแรกให้แยก zsh ออกจากส่วนที่เหลือ มันไม่ได้เป็นเรื่องของเปลือกหอยแบบเก่ากับสมัยใหม่: zsh ทำงานแตกต่างกัน ผู้ออกแบบ zsh ตัดสินใจที่จะไม่เข้ากับเชลล์แบบดั้งเดิม (Bourne, ksh, bash) แต่ใช้งานได้ง่ายกว่า
ประการที่สองมันง่ายกว่ามากที่จะใช้เครื่องหมายคำพูดคู่ตลอดเวลามากกว่าที่จะจำได้เมื่อจำเป็น พวกเขาต้องการเวลาส่วนใหญ่ดังนั้นคุณจะต้องเรียนรู้เมื่อไม่ต้องการไม่ใช่เมื่อจำเป็น
สรุปราคาคู่มีความจำเป็นที่ใดก็ตามที่รายการของคำหรือรูปแบบที่เป็นที่คาดหวัง พวกเขาเป็นทางเลือกในบริบทที่คาดว่าจะเป็นสตริงดิบโดย parser
จะเกิดอะไรขึ้นถ้าไม่มีคำพูด
โปรดทราบว่าหากไม่มีเครื่องหมายคำพูดคู่จะมีสองสิ่งเกิดขึ้น
- ก่อนผลลัพธ์ของการขยาย (ค่าของตัวแปรสำหรับการทดแทนพารามิเตอร์เช่น
${foo}
หรือผลลัพธ์ของคำสั่งสำหรับการทดแทนคำสั่งเช่น$(foo)
) จะแบ่งออกเป็นคำที่มันมีช่องว่าง
แม่นยำยิ่งขึ้นผลลัพธ์ของการขยายตัวจะถูกแยกออกเป็นอักขระแต่ละตัวที่ปรากฏในค่าของIFS
ตัวแปร (อักขระตัวคั่น) หากลำดับของอักขระตัวคั่นมีช่องว่าง (เว้นวรรคแท็บหรือขึ้นบรรทัดใหม่) ช่องว่างจะถูกนับเป็นอักขระตัวเดียว นำหน้าตัวต่อท้ายหรือตัวคั่นที่ไม่ใช่ช่องว่างซ้ำ ๆ นำไปสู่ฟิลด์ว่าง ตัวอย่างเช่นกับIFS=" :"
, :one::two : three: :four
ผลิตสนามว่างเปล่าก่อนone
ระหว่างone
และtwo
และ (หนึ่งเดียว) ระหว่างและthree
four
- ข้อมูลที่เกิดจากการแยกแต่ละครั้งจะถูกตีความว่าเป็น glob (รูปแบบสัญลักษณ์แทน)
\[*?
ถ้ามีหนึ่งในตัวละคร หากรูปแบบนั้นตรงกับชื่อไฟล์หนึ่งชื่อขึ้นไปรูปแบบนั้นจะถูกแทนที่ด้วยรายการชื่อไฟล์ที่ตรงกัน
การขยายตัวของตัวแปร unquoted $foo
เป็นที่รู้จักเรียกขานว่า“แยก + glob ผู้ประกอบการ” ในทางตรงกันข้ามกับที่ใช้เวลาเพียงค่าของตัวแปร"$foo"
foo
การทดแทนคำสั่งที่เหมือนกัน"$(foo)"
คือการทดแทน$(foo)
คำสั่งเป็นการแทนที่คำสั่งตามด้วย split + glob
ที่ที่คุณสามารถละเว้นเครื่องหมายคำพูดคู่
นี่คือทุกกรณีที่ฉันนึกถึงในเชลล์สไตล์ Bourne ซึ่งคุณสามารถเขียนการทดแทนตัวแปรหรือคำสั่งโดยไม่ใส่เครื่องหมายอัญประกาศคู่และค่าจะถูกตีความอย่างแท้จริง
ทางด้านขวาของการมอบหมาย
var=$stuff
a_single_star=*
โปรดทราบว่าคุณจำเป็นต้องใส่เครื่องหมายคำพูดคู่หลังจากexport
นั้นเพราะมันเป็นบิวด์อินปกติไม่ใช่คำหลัก สิ่งนี้เป็นจริงในเชลล์บางตัวเช่น dash, zsh (เป็น sh emulation), yash หรือ posh; ทุบตีและ ksh ทั้งสองปฏิบัติexport
เป็นพิเศษ
export VAR="$stuff"
ในcase
งบ
case $var in …
โปรดทราบว่าคุณจำเป็นต้องมีเครื่องหมายคำพูดคู่ในรูปแบบตัวพิมพ์เล็กและตัวพิมพ์ใหญ่ การแยกคำไม่ได้เกิดขึ้นในรูปแบบตัวพิมพ์เล็ก แต่ตัวแปรที่ไม่มีเครื่องหมายถูกตีความว่าเป็นรูปแบบในขณะที่ตัวแปรที่ยกมาถูกตีความว่าเป็นสตริงตัวอักษร
a_star='a*'
case $var in
"$a_star") echo "'$var' is the two characters a, *";;
$a_star) echo "'$var' begins with a";;
esac
ภายในวงเล็บเหลี่ยมสองอัน เครื่องหมายวงเล็บคู่เป็นไวยากรณ์พิเศษของเชลล์
[[ -e $filename ]]
ยกเว้นว่าคุณจะต้องมีคำพูดคู่ที่รูปแบบหรือการแสดงออกปกติคาดว่าทางด้านขวามือของ=
หรือ==
หรือหรือ!=
=~
a_star='a*'
if [[ $var == "$a_star" ]]; then echo "'$var' is the two characters a, *"
elif [[ $var == $a_star ]]; then echo "'$var' begins with a"
fi
คุณต้องการอัญประกาศคู่ตามปกติภายในวงเล็บปีกกาเดียว[ … ]
เนื่องจากเป็นเชลล์ไวยากรณ์ทั่วไป (เป็นคำสั่งที่จะเรียกใช้[
) ดูวงเล็บเหลี่ยมเดี่ยวหรือคู่
ในการเปลี่ยนเส้นทางในเชลล์ POSIX แบบไม่โต้ตอบ (ไม่ใช่bash
, หรือksh88
)
echo "hello world" >$filename
เชลล์บางตัวเมื่อทำปฏิกิริยาจะถือว่าค่าของตัวแปรเป็นรูปแบบไวด์การ์ด POSIX ห้ามพฤติกรรมดังกล่าวในเชลล์ที่ไม่มีการโต้ตอบ แต่เชลล์บางตัวรวมถึง bash (ยกเว้นในโหมด POSIX) และ ksh88 (รวมถึงเมื่อพบว่าเป็น POSIX sh
ของ Unices เชิงพาณิชย์เช่น Solaris) ที่ยังคงทำอยู่ ( bash
เช่นพยายามแยกและการเปลี่ยนเส้นทางล้มเหลวเว้นแต่ว่าการแบ่ง + การแบ่งเป็นวงกลมจะมีคำเดียว) ซึ่งเป็นเหตุผลที่ดีกว่าที่จะอ้างถึงเป้าหมายของการเปลี่ยนเส้นทางในsh
สคริปต์ในกรณีที่คุณต้องการแปลงเป็นbash
สคริปต์ในบางวันหรือเรียกใช้บนระบบที่sh
เป็น ไม่สอดคล้องกับจุดนั้นหรืออาจมาจากเชลล์แบบโต้ตอบ
ภายในนิพจน์ทางคณิตศาสตร์ ในความเป็นจริงคุณจำเป็นต้องเว้นเครื่องหมายอัญประกาศเพื่อให้ตัวแปรแยกวิเคราะห์เป็นนิพจน์ทางคณิตศาสตร์
expr=2*2
echo "$(($expr))"
อย่างไรก็ตามคุณจำเป็นต้องมีเครื่องหมายอัญประกาศล้อมรอบส่วนขยายคณิตศาสตร์เนื่องจากจะต้องมีการแบ่งคำในเชลล์ส่วนใหญ่ตามที่ POSIX ต้องการ (!?)
ในตัวห้อยอาร์เรย์ที่เชื่อมโยง
typeset -A a
i='foo bar*qux'
a[foo\ bar\*qux]=hello
echo "${a[$i]}"
ตัวแปรที่ไม่ได้กล่าวถึงและการทดแทนคำสั่งอาจมีประโยชน์ในบางสถานการณ์ที่หายาก:
- เมื่อค่าตัวแปรหรือเอาต์พุตคำสั่งประกอบด้วยรายการของรูปแบบ glob และคุณต้องการที่จะขยายรูปแบบเหล่านี้ไปยังรายการของไฟล์ที่ตรงกัน
- เมื่อคุณรู้ว่าค่าไม่มีอักขระตัวแทนใด ๆ นั่น
$IFS
ก็ไม่ได้ถูกแก้ไขและคุณต้องการแยกเป็นอักขระช่องว่าง
- เมื่อคุณต้องการแยกค่าที่ตัวอักขระบางตัว: ปิดการใช้งานแบบวนรอบด้วย
set -f
ตั้งค่าIFS
เป็นตัวคั่น
zsh
ใน zsh คุณสามารถละเว้นเครื่องหมายคำพูดคู่ได้เกือบทุกครั้งโดยมีข้อยกเว้นบางประการ
$var
ไม่เคยขยายไปหลายคำ แต่จะขยายไปยังรายการที่ว่างเปล่า (ตรงข้ามกับรายการที่มีคำเดียวที่ว่างเปล่า) หากค่าของvar
คือสตริงที่ว่างเปล่า คมชัด:
var=
print -l $var foo # prints just foo
print -l "$var" foo # prints an empty line, then foo
ในทำนองเดียวกัน"${array[@]}"
ขยายองค์ประกอบทั้งหมดของอาร์เรย์ในขณะที่$array
ขยายไปยังองค์ประกอบที่ไม่ว่างเปล่าเท่านั้น
ธงขยายตัวพารามิเตอร์บางครั้งต้องใช้คำพูดสองรอบการเปลี่ยนตัวผู้เล่นทั้งหมด:@
"${(@)foo}"
การทดแทนคำสั่งผ่านการแยกฟิลด์หากไม่ได้อ้างอิง: echo $(echo 'a'; echo '*')
พิมพ์a *
(ด้วยช่องว่างเดียว) ในขณะที่echo "$(echo 'a'; echo '*')"
พิมพ์สตริงสองบรรทัดที่ไม่ได้แก้ไข ใช้"$(somecommand)"
เพื่อให้ได้ผลลัพธ์ของคำสั่งในคำเดียวบรรทัดใหม่สุดท้าย ใช้"${$(somecommand; echo _)%?}"
เพื่อรับเอาต์พุตที่แน่นอนของคำสั่งรวมถึงการขึ้นบรรทัดใหม่ ใช้"${(@f)$(somecommand)}"
เพื่อรับอาร์เรย์ของบรรทัดจากเอาต์พุตของคำสั่ง
SH_WORD_SPLIT
ตัวเลือก