สคริปต์ของคุณใช้คุณสมบัติสามอย่างของ Bash shell ซึ่งไม่ได้จัดทำโดยเชลล์สไตล์ Bourne ทั้งหมด ในฐานะที่เป็นheemayl บอกว่าคุณก็สามารถเรียกใช้สคริปต์ที่มีแทนbash shคุณhashbangบรรทัดที่ด้านบน ( #!/bin/bash) ระบุbashแต่จะมีผลเฉพาะถ้าคุณรันสคริปต์ที่เป็นheemayl อธิบาย หากคุณส่งชื่อของสคริปต์เพื่อsh, shจะไม่เรียกโดยอัตโนมัติbashแต่ก็จะเรียกใช้สคริปต์ เนื่องจากเมื่อสคริปต์ของคุณทำงานจริงบรรทัด hashbang จะไม่มีผลใดๆ
ทางเลือกอื่น ๆ ของคุณหากคุณต้องการเขียนสคริปต์แบบพกพาที่ไม่ขึ้นอยู่กับคุณสมบัติของ Bash คือการเปลี่ยนสคริปต์ของคุณเพื่อให้สคริปต์ทำงานได้โดยไม่ต้องใช้สคริปต์ คุณสมบัติ Bash ที่คุณใช้คือ:
- อาร์เรย์ นี้มาก่อนดังนั้นนี่คือสิ่งที่ผลิตข้อผิดพลาดเมื่อคุณพยายามที่จะเรียกใช้สคริปต์ของคุณกับเปลือกชน นิพจน์เครื่องหมายวงเล็บ
( {a..z} )ซึ่งคุณกำหนดให้charsสร้างอาร์เรย์และ${chars[i]}ซึ่งปรากฏในลูปของคุณจะจัดทำดัชนีในอาร์เรย์
- การขยายรั้ง ในทุบตีและยังอยู่ในเปลือกหอยอื่น ๆ อีกมากมายมีการขยายไปยัง
{a..z} a b c d e f g h i j k l m n o p q r s t u v w x y zอย่างไรก็ตามนี่ไม่ใช่คุณสมบัติสากล (หรือเป็นมาตรฐาน) ของเชลล์สไตล์ Bourne และ Dash ไม่รองรับ
- ไวยากรณ์ C- สไตล์ทางเลือก -
forลูป แม้ว่าจะขึ้นอยู่กับการขยายตัวทางคณิตศาสตร์ซึ่งไม่ได้ระบุเฉพาะกับ Bash (แม้ว่าบางเชลล์ที่เก่าและไม่ใช่ POSIX ที่เข้ากันไม่ได้ก็ตาม) C-style forloop เป็น Bash-ism และไม่สามารถพกพาไปได้อย่างกว้างขวาง กระสุนอื่น ๆ
Bash พร้อมใช้งานอย่างกว้างขวางโดยเฉพาะอย่างยิ่งในระบบ GNU / Linux เช่น Ubuntu และ (ตามที่คุณเห็น) ยังมีอยู่ใน macOS และระบบอื่น ๆ อีกมากมาย เมื่อพิจารณาว่าคุณใช้คุณลักษณะเฉพาะของ Bash คุณอาจต้องการใช้คุณลักษณะเหล่านั้นและตรวจสอบให้แน่ใจว่าคุณกำลังใช้ Bash (หรือเชลล์อื่น ๆ ที่สนับสนุนคุณสมบัติที่คุณใช้) เมื่อคุณเรียกใช้สคริปต์
อย่างไรก็ตามคุณสามารถแทนที่ด้วยโครงสร้างแบบพกพาได้หากต้องการ อาเรย์และ C-style forloop นั้นง่ายต่อการเปลี่ยน การสร้างช่วงของตัวอักษรโดยไม่มีการขยายรั้ง (และไม่มีการเข้ารหัสอย่างหนักในสคริปต์ของคุณ) เป็นส่วนหนึ่งที่ค่อนข้างยุ่งยาก
ก่อนอื่นนี่คือสคริปต์ที่พิมพ์ตัวอักษรละตินตัวพิมพ์เล็กทั้งหมด:
#!/bin/sh
for i in $(seq 97 122); do
printf "\\$(printf %o $i)\n"
done
seqคำสั่งสร้างลำดับตัวเลข $( )ดำเนินการคำสั่งเปลี่ยนตัวจึงถูกแทนที่ด้วยการส่งออกของ$(seq 97 122) seq 97 122เหล่านี้เป็นรหัสอักขระสำหรับผ่านaz
printfคำสั่งที่มีประสิทธิภาพสามารถเปลี่ยนรหัสตัวอักษรให้เป็นตัวอักษร (เช่นprintf '\141'พิมพ์aตามด้วยบรรทัดใหม่ ) แต่รหัสจะต้องอยู่ในรูปฐานแปดในขณะที่seqเอาท์พุทเป็นทศนิยมเท่านั้น ดังนั้นฉันจึงใช้printfสองครั้ง: Inner printf %o $iแปลงตัวเลขทศนิยม (ให้โดยseq) เป็นฐานแปดและแทนที่ด้วยprintfคำสั่งouter (แม้ว่าจะเป็นไปได้ที่จะใช้เลขฐานสิบหกแต่ก็ไม่ง่ายและดูเหมือนจะพกพาได้น้อยลง )
printfตีความ\ตามด้วยหมายเลขฐานแปดเป็นอักขระที่มีรหัสนั้นและ\nเป็นบรรทัดใหม่ แต่เชลล์ยังใช้\เป็นอักขระยกเว้น \ในด้านหน้าของ$จะป้องกันไม่ให้$จากที่ก่อให้เกิดการขยายตัวที่จะเกิดขึ้น (ในกรณีนี้แทนคำสั่ง ) แต่ฉันไม่ต้องการที่จะป้องกันไม่ให้ดังนั้นฉันได้หนีด้วยอื่น\; \\นั่นคือเหตุผลที่ ที่สอง\ก่อนที่จะnไม่จำเป็นที่จะต้องหนีเพราะไม่เหมือน\$, \nไม่ได้มีความหมายพิเศษกับเปลือกในสตริงยกมาสองครั้ง
- สำหรับข้อมูลเพิ่มเติมเกี่ยวกับวิธีการและคำพูดทับขวาคู่ถูกนำมาใช้ในการเขียนโปรแกรมเปลือกดูส่วนที่เกี่ยวกับข้อความในมาตรฐานสากล ดูเพิ่มเติม3.1.2 Quotingในคู่มือการทุบตีอ้างอิงโดยเฉพาะอย่างยิ่ง3.1.2.1 ตัวหนีและ3.1.2.3 คำพูดคู่ (นี่คือส่วนทั้งหมดตามบริบท) โปรดทราบว่าเครื่องหมายอัญประกาศเดี่ยว (
') เป็นส่วนสำคัญของไวยากรณ์ข้อความเปลือกหอยฉันไม่ได้ใช้มันในสคริปต์นั้น
สิ่งนี้สามารถพกพาไปได้กับระบบที่เหมือน Unix ส่วนใหญ่และไม่ได้ขึ้นอยู่กับเชลล์สไตล์ Bourne ที่คุณใช้ อย่างไรก็ตามระบบที่คล้าย Unix บางตัวไม่ได้seqติดตั้งไว้ตามค่าเริ่มต้น (มักจะใช้jotแทนซึ่งไม่ได้ติดตั้งตามค่าเริ่มต้นของระบบ GNU / Linux ส่วนใหญ่) คุณสามารถใช้การวนซ้ำด้วยexprหรือการแทนที่ทางคณิตศาสตร์เพื่อเพิ่มความสะดวกในการพกพาเพิ่มเติมหากคุณต้องการ:
#!/bin/sh
i=97
while [ $i -le 122 ]; do
printf "\\$(printf %o $i)\n"
i=$((i + 1))
done
ที่ใช้while-loop กับคำสั่งเพื่อดำเนินการต่อบ่วงเฉพาะเมื่ออยู่ในช่วง[$i
แทนที่จะพิมพ์ตัวอักษรทั้งหมดสคริปต์ของคุณจะกำหนดตัวแปรnและพิมพ์$nตัวอักษรพิมพ์เล็กตัวแรก นี่คือเวอร์ชันของสคริปต์ของคุณที่ไม่ขึ้นอยู่กับฟีเจอร์เฉพาะของ Bash และใช้งานได้บน Dash แต่ต้องการseq:
#!/bin/sh
n=3 start=97
for i in $(seq $start $((start + n - 1))); do
printf "\\$(printf %o $i)\n"
done
การปรับค่าnการเปลี่ยนแปลงจำนวนตัวอักษรที่พิมพ์เช่นเดียวกับในสคริปต์ของคุณ
นี่คือรุ่นที่ไม่ต้องการseq:
#!/bin/sh
n=3 i=97 stop=$((i + n))
while [ $i -lt $stop ]; do
printf "\\$(printf %o $i)\n"
i=$((i + 1))
done
มี$stopหนึ่งสูงกว่ารหัสตัวอักษรของตัวอักษรสุดท้ายที่ควรจะพิมพ์ดังนั้นฉันใช้-lt(น้อยกว่า) มากกว่า-le(น้อยกว่าหรือเท่ากับ) ด้วย[คำสั่ง (มันจะต้องทำงานstop=$((i + n - 1))และใช้งานด้วย[ $i -le $stop ])