Computer >> บทช่วยสอนคอมพิวเตอร์ >  >> การเขียนโปรแกรม >> การเขียนโปรแกรม Bash

เชี่ยวชาญการ Parse Options ในสคริปต์ Bash: คู่มือทีละขั้นตอน

คำสั่งเทอร์มินัลปกติจะมีตัวเลือก (options) หรือสวิตช์ (switches) ที่คุณสามารถใช้เพื่อปรับเปลี่ยนวิธีการทำงานของคำสั่ง ตัวเลือกถูกรวมอยู่ในข้อกำหนด POSIX สำหรับอินเทอร์เฟซบรรทัดคำสั่ง นี่ยังเป็นข้อตกลงที่สืบมาตั้งแต่แอปพลิเคชัน UNIX เริ่มต้น จึงเป็นเรื่องดีที่ควรรู้วิธีรวมพวกมันในสคริปต์ Bash ของคุณเมื่อคุณสร้างคำสั่งของตัวเอง

เหมือนกับภาษาส่วนใหญ่ มีหลายวิธีในการแก้ปัญหาการ parse options ใน Bash จนถึงวันนี้ วิธีที่ผมชอบมากที่สุดยังคงเป็นวิธีที่ผมเรียนรู้จากสคริปต์สร้าง Slackware ของ Patrick Volkerding ซึ่งเป็นการแนะนำสู่ shell scripting ของผม ตอนที่ผมค้นพบ Linux และกล้าเข้าไปดูไฟล์ข้อความธรรมดาที่มาพร้อมกับ OS

การ Parse Options ใน Bash

กลยุทธ์สำหรับการ parse options ใน Bash คือ วนลูปผ่านอาร์กิวเมนต์ทั้งหมดที่ส่งให้ shell script ตรวจสอบว่าพวกมันเป็น option หรือไม่ แล้ว shift ไปยังอาร์กิวเมนต์ถัดไป ทำซ้ำกระบวนการนี้จนกว่าจะไม่มี options เหลือ

เริ่มต้นด้วยตัวเลือก Boolean แบบง่าย (บางครั้งเรียกว่า switch หรือ flag):

#!/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 (นี่คือชื่อตัวเลือก tùy ý ไม่มีความหมายพิเศษ ในสคริปต์จริง คุณอาจใช้ --verbose และ -v เพื่อเปิดโหมด verbose output)

คีย์เวิร์ด 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 เหมือนกับ boolean switches แต่ 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

การ Parse Options อย่างง่ายดาย

มีวิธีอื่นๆ ในการ parse options ใน Bash คุณสามารถใช้คำสั่ง case หรือคำสั่ง getopt ได้เช่นกัน 无论你选择使用什么,选项对于您的用户来说都是任何应用程序的重要功能,而 Bash 使其变得简单。