เชลล์คล้าย Bourne / POSIX มีตัวดำเนินการแยก + glob และมีการเรียกใช้ทุกครั้งที่คุณออกจากการขยายพารามิเตอร์ ( $var, $-... ), การแทนที่คำสั่ง ( $(...)) หรือการขยายเลขคณิต ( $((...))) ไม่ได้ระบุไว้ในบริบทรายการ
ที่จริงแล้วคุณเรียกมันโดยไม่ได้ตั้งใจเมื่อคุณทำแทนfor name in ${array[@]} for name in "${array[@]}"(ที่จริงแล้วคุณควรระวังที่เรียกใช้ตัวดำเนินการนั้นโดยไม่ตั้งใจว่าเป็นแหล่งที่มาของข้อบกพร่องและจุดอ่อนด้านความปลอดภัย )
ผู้ประกอบการที่มีการกำหนดค่าด้วย$IFSพารามิเตอร์พิเศษ (จะบอกสิ่งที่ตัวอักษรเพื่อแยก ( แต่ระวังว่าพื้นที่แท็บและการขึ้นบรรทัดใหม่ได้รับการดูแลเป็นพิเศษมี)) และ-fตัวเลือกที่จะปิดการใช้งาน ( set -f) หรือเปิดใช้งาน ( set +f) ด้วยglobส่วนหนึ่ง
นอกจากนี้โปรดทราบว่าในขณะที่Sอิน$IFSคือเดิม (ในเชลล์เป้าหมายที่$IFSมาจาก) สำหรับSeparator ใน POSIX เชลล์อักขระใน$IFSควรจะถูกมองว่าเป็นตัวคั่นหรือเทอร์มิเนเตอร์ (ดูตัวอย่างด้านล่าง)
ดังนั้นเพื่อแยก_:
string='var1_var2_var3'
IFS=_ # delimit on _
set -f # disable the glob part
array=($string) # invoke the split+glob operator
for i in "${array[@]}"; do # loop over the array elements.
หากต้องการดูความแตกต่างระหว่างตัวคั่นและตัวคั่นให้ลองทำดังนี้:
string='var1_var2_'
ที่จะแยกไว้ในvar1และvar2เท่านั้น (องค์ประกอบที่ว่างเปล่าไม่มีเสริม)
ดังนั้นเพื่อให้คล้ายกับ JavaScript split()คุณต้องมีขั้นตอนเพิ่มเติม:
string='var1_var2_var3'
IFS=_ # delimit on _
set -f # disable the glob part
temp=${string}_ # add an extra delimiter
array=($temp) # invoke the split+glob operator
(โปรดทราบว่ามันจะแบ่งค่าว่าง$stringเป็น1 (ไม่ใช่0 ) องค์ประกอบเช่น JavaScript split())
หากต้องการดูแท็บการรักษาพิเศษพื้นที่และการขึ้นบรรทัดใหม่ให้เปรียบเทียบ:
IFS=' '; string=' var1 var2 '
(ที่คุณได้รับvar1และvar2) ด้วย
IFS='_'; string='_var1__var2__'
ที่คุณจะได้รับ: '', var1, '', ,var2''
โปรดทราบว่าzshเชลล์ไม่ได้เรียกใช้ตัวดำเนินการแยก + glob โดยปริยายเช่นนั้นยกเว้นในshหรือkshจำลอง ที่นั่นคุณต้องเรียกใช้มันอย่างชัดเจน $=stringสำหรับส่วนที่แยก$~stringสำหรับส่วน glob ( $=~stringสำหรับทั้งสอง) และมันยังมีตัวดำเนินการแยกที่คุณสามารถระบุตัวแยก:
array=(${(s:_:)string})
หรือเพื่อรักษาองค์ประกอบที่ว่างเปล่า:
array=("${(@s:_:)string}")
โปรดทราบว่ามีsการแยกไม่คั่น (รวม$IFSถึง POSIX ที่ไม่สอดคล้องกันzsh) มันแตกต่างจาก JavaScript split()ในที่สตริงว่างถูกแบ่งออกเป็นองค์ประกอบ 0 (ไม่ใช่ 1)
ความแตกต่างที่โดดเด่นด้วย$IFS-splitting คือ${(s:abc:)string}แยกบนabcสตริงในขณะที่มีการIFS=abcที่จะแยกa, หรือbc
ด้วยzshและการรักษาพิเศษที่พื้นที่แท็บหรือขึ้นบรรทัดใหม่ได้รับสามารถลบออกได้โดยการเพิ่มพวกเขาในksh93$IFS
ในฐานะที่เป็นบันทึกประวัติศาสตร์เชลล์บอร์น (เชลล์บรรพบุรุษหรือ POSIX เชลล์สมัยใหม่) ลอกองค์ประกอบที่ว่างเปล่าเสมอ นอกจากนี้ยังมีจำนวนของข้อบกพร่องที่เกี่ยวข้องกับการแยกและการขยายตัวของ $ @ $IFSมีค่าที่ไม่ใช่การเริ่มต้นของ ยกตัวอย่างเช่นจะไม่เทียบเท่ากับIFS=_; set -f; set -- $@IFS=_; set -f; set -- $1 $2 $3...
แยกบน regexps
ตอนนี้สำหรับบางสิ่งที่ใกล้เคียงกับ JavaScript split()ที่สามารถแยกการแสดงผลปกติคุณต้องพึ่งพาโปรแกรมอรรถประโยชน์ภายนอก
ใน POSIX Tool-chest awkมีsplitโอเปอเรเตอร์ที่สามารถแยกนิพจน์ปกติแบบขยาย (ซึ่งเป็นชุดย่อยของนิพจน์ปกติเหมือน Perl ที่สนับสนุนโดย JavaScript)
split() {
awk -v q="'" '
function quote(s) {
gsub(q, q "\\" q q, s)
return q s q
}
BEGIN {
n = split(ARGV[1], a, ARGV[2])
for (i = 1; i <= n; i++) printf " %s", quote(a[i])
exit
}' "$@"
}
string=a__b_+c
eval "array=($(split "$string" '[_+]+'))"
zshเปลือกมีในตัวสนับสนุนสำหรับการแสดงออกปกติ Perl เข้ากันได้ (ในของzsh/pcreโมดูล) แต่ใช้มันเพื่อแยกสตริง แต่ที่เป็นไปได้ค่อนข้างยุ่งยาก
shellที่คุณใช้กับbashที่คุณสามารถทำได้IFS='_' read -a array <<< "${string}"