คำสั่ง Terminal มักมีตัวเลือกหรือสวิตช์ ซึ่งคุณสามารถใช้เพื่อปรับเปลี่ยนวิธีที่คำสั่งทำงาน ตัวเลือกรวมอยู่ในข้อกำหนด POSIX สำหรับอินเทอร์เฟซบรรทัดคำสั่ง นอกจากนี้ยังเป็นข้อตกลงที่ให้เกียรติกับเวลาซึ่งสร้างขึ้นด้วยแอปพลิเคชัน UNIX ที่เก่าที่สุด ดังนั้นจึงควรทราบวิธีรวมไว้ในสคริปต์ Bash เมื่อคุณสร้างคำสั่งของคุณเอง
เช่นเดียวกับภาษาส่วนใหญ่ มีหลายวิธีในการแก้ปัญหาตัวเลือกการแยกวิเคราะห์ใน Bash จนถึงทุกวันนี้ วิธีโปรดของฉันยังคงเป็นวิธีที่ฉันเรียนรู้จากสคริปต์บิลด์ Slackware ของ Patrick Volkerding ซึ่งทำหน้าที่เป็นคำแนะนำเบื้องต้นเกี่ยวกับเชลล์สคริปต์ในตอนที่ฉันค้นพบ Linux ครั้งแรกและกล้าที่จะเสี่ยงกับไฟล์ข้อความธรรมดาที่มาพร้อมกับระบบปฏิบัติการ P>
ตัวเลือกการแยกวิเคราะห์ใน Bash
กลยุทธ์ในการแยกวิเคราะห์ตัวเลือกใน Bash คือการวนรอบอาร์กิวเมนต์ทั้งหมดที่ส่งผ่านไปยังเชลล์สคริปต์ของคุณ พิจารณาว่าเป็นตัวเลือกหรือไม่ จากนั้นเลื่อนไปที่อาร์กิวเมนต์ถัดไป ทำขั้นตอนนี้ซ้ำจนกว่าจะไม่มีตัวเลือกเหลืออยู่
เริ่มต้นด้วยตัวเลือกบูลีน (บางครั้งเรียกว่า สวิตช์ หรือ ธง ):
#!/bin/bash
while [ True ]; do
if [ "$1" = "--alpha" -o "$1" = "-a" ]; then
ALPHA=1
shift 1
else
break
fi
done
echo $ALPHA
ในรหัสนี้ ฉันสร้าง while
วนซ้ำซึ่งทำหน้าที่เป็นวงวนไม่สิ้นสุดจนกว่าจะไม่มีการโต้แย้งเพิ่มเติมในการประมวลผล if
คำสั่งพยายามจับคู่อาร์กิวเมนต์ใดๆ ก็ตามที่พบในตำแหน่งแรก ($1
) เป็น --alpha
หรือ -a
. (นี่คือชื่อตัวเลือกตามอำเภอใจที่ไม่มีนัยสำคัญเป็นพิเศษ ในสคริปต์จริง คุณอาจใช้ --verbose
และ -v
เพื่อทริกเกอร์เอาต์พุตแบบละเอียด)
shift
คีย์เวิร์ดทำให้อาร์กิวเมนต์ทั้งหมดเปลี่ยนไป 1 ดังนั้นอาร์กิวเมนต์ในตำแหน่ง 2 ($2
) ถูกย้ายไปตำแหน่ง 1 ($1
). else
คำสั่งจะถูกเรียกใช้เมื่อไม่มีอาร์กิวเมนต์เพิ่มเติมในการประมวลผล ซึ่งทำลาย while
วนซ้ำ
ที่ส่วนท้ายของสคริปต์ ค่าของ $ALPHA
ถูกพิมพ์ไปยังเครื่องปลายทาง
ทดสอบสคริปต์:
$ bash ./test.sh --alpha
1
$ bash ./test.sh
$ bash ./test.sh -a
1
ตรวจพบตัวเลือกอย่างถูกต้อง
การตรวจจับอาร์กิวเมนต์ใน Bash
มีปัญหาแม้ว่า:อาร์กิวเมนต์พิเศษจะถูกละเว้น
$ bash ./test.sh --alpha foo
1
$
ในการดักจับอาร์กิวเมนต์ที่ไม่ได้มีไว้สำหรับตัวเลือก คุณสามารถดัมพ์อาร์กิวเมนต์ที่เหลือลงในอาร์เรย์ Bash
#!/bin/bash
while [ True ]; do
if [ "$1" = "--alpha" -o "$1" = "-a" ]; then
ALPHA=1
shift 1
else
break
fi
done
echo $ALPHA
ARG=( "${@}" )
for i in ${ARG[@]}; do
echo $i
done
ทดสอบเวอร์ชันใหม่ของสคริปต์:
$ bash ./test.sh --alpha foo
1
foo
$ bash ./test.sh foo
foo
$ bash ./test.sh --alpha foo bar
1
foo
bar
ตัวเลือกที่มีอาร์กิวเมนต์
บางตัวเลือกต้องการอาร์กิวเมนต์ทั้งหมดของตัวเอง ตัวอย่างเช่น คุณอาจต้องการอนุญาตให้ผู้ใช้ตั้งค่าแอตทริบิวต์ เช่น สีหรือความละเอียดของกราฟิก หรือกำหนดให้แอปพลิเคชันของคุณไปที่ไฟล์การกำหนดค่าที่กำหนดเอง
ในการใช้งาน Bash คุณสามารถใช้ shift
คีย์เวิร์ดเหมือนกับที่คุณทำกับสวิตช์บูลีน แต่เปลี่ยนอาร์กิวเมนต์เป็น 2 แทนที่จะเป็น 1
#!/bin/bash
while [ True ]; do
if [ "$1" = "--alpha" -o "$1" = "-a" ]; then
ALPHA=1
shift 1
elif [ "$1" = "--config" -o "$1" = "-c" ]; then
CONFIG=$2
shift 2
else
break
fi
done
echo $ALPHA
echo $CONFIG
ARG=( "${@}" )
for i in ${ARG[@]}; do
echo $i
done
ในรหัสนี้ ฉันเพิ่ม elif
ประโยคเพื่อเปรียบเทียบแต่ละอาร์กิวเมนต์กับทั้ง --config
และ -c
. ในกรณีที่มีการจับคู่ ค่าของตัวแปรที่เรียกว่า CONFIG
ถูกกำหนดเป็นค่าของอาร์กิวเมนต์ที่สอง (ซึ่งหมายความว่า --config
ตัวเลือกต้องมีอาร์กิวเมนต์) อาร์กิวเมนต์ทั้งหมดเลื่อนตำแหน่ง 2:1 เพื่อเลื่อน --config
หรือ -c
และ 1 เพื่อย้ายอาร์กิวเมนต์ ตามปกติ การวนซ้ำจะวนซ้ำจนกว่าจะไม่มีอาร์กิวเมนต์ที่ตรงกันเหลืออยู่
นี่คือการทดสอบสคริปต์เวอร์ชันใหม่:
$ bash ./test.sh --config my.conf foo bar
my.conf
foo
bar
$ bash ./test.sh -a --config my.conf baz
1
my.conf
baz
การแยกวิเคราะห์ตัวเลือกทำได้ง่าย
มีวิธีอื่นในการแยกวิเคราะห์ตัวเลือกใน Bash คุณสามารถใช้ case
. แทนได้ คำสั่งหรือ getopt
สั่งการ. ไม่ว่าคุณจะเลือกใช้ตัวเลือกใด ตัวเลือกสำหรับผู้ใช้ของคุณก็เป็นคุณสมบัติที่สำคัญสำหรับแอปพลิเคชันใดๆ และ Bash ก็ทำให้เป็นเรื่องง่าย