สคริปต์ของคุณใช้คุณสมบัติสามอย่างของ 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 for
loop เป็น Bash-ism และไม่สามารถพกพาไปได้อย่างกว้างขวาง กระสุนอื่น ๆ
Bash พร้อมใช้งานอย่างกว้างขวางโดยเฉพาะอย่างยิ่งในระบบ GNU / Linux เช่น Ubuntu และ (ตามที่คุณเห็น) ยังมีอยู่ใน macOS และระบบอื่น ๆ อีกมากมาย เมื่อพิจารณาว่าคุณใช้คุณลักษณะเฉพาะของ Bash คุณอาจต้องการใช้คุณลักษณะเหล่านั้นและตรวจสอบให้แน่ใจว่าคุณกำลังใช้ Bash (หรือเชลล์อื่น ๆ ที่สนับสนุนคุณสมบัติที่คุณใช้) เมื่อคุณเรียกใช้สคริปต์
อย่างไรก็ตามคุณสามารถแทนที่ด้วยโครงสร้างแบบพกพาได้หากต้องการ อาเรย์และ C-style for
loop นั้นง่ายต่อการเปลี่ยน การสร้างช่วงของตัวอักษรโดยไม่มีการขยายรั้ง (และไม่มีการเข้ารหัสอย่างหนักในสคริปต์ของคุณ) เป็นส่วนหนึ่งที่ค่อนข้างยุ่งยาก
ก่อนอื่นนี่คือสคริปต์ที่พิมพ์ตัวอักษรละตินตัวพิมพ์เล็กทั้งหมด:
#!/bin/sh
for i in $(seq 97 122); do
printf "\\$(printf %o $i)\n"
done
seq
คำสั่งสร้างลำดับตัวเลข $(
)
ดำเนินการคำสั่งเปลี่ยนตัวจึงถูกแทนที่ด้วยการส่งออกของ$(seq 97 122)
seq 97 122
เหล่านี้เป็นรหัสอักขระสำหรับผ่านa
z
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 ]
)