พารามิเตอร์สคริปต์ใน Bash


104

ฉันกำลังพยายามสร้างเชลล์สคริปต์ซึ่งควรใช้ในลักษณะนี้:

ocrscript.sh -from /home/kristoffer/test.png -to /home/kristoffer/test.txt

จากนั้นสคริปต์ ocr จะแปลงไฟล์รูปภาพเป็นไฟล์ข้อความ นี่คือสิ่งที่ฉันคิดมาจนถึงตอนนี้:

#!/bin/bash
export HOME=/home/kristoffer
/usr/local/bin/abbyyocr9 -rl Swedish -if ???fromvalue??? -of ???tovalue??? 2>&1

แต่ฉันไม่รู้วิธีรับ-fromและ-toค่า มีแนวคิดในการทำอย่างไร?


คำตอบ:


125

ข้อโต้แย้งที่คุณให้กับ bashscript จะปรากฏในตัวแปร$1และ$2และ$3จำนวนที่หมายถึงการโต้แย้ง $0เป็นคำสั่งเอง

อาร์กิวเมนต์ถูกคั่นด้วยช่องว่างดังนั้นหากคุณระบุ-fromและ-toในคำสั่งก็จะลงเอยด้วยตัวแปรเหล่านี้เช่นกันสำหรับสิ่งนี้:

./ocrscript.sh -from /home/kristoffer/test.png -to /home/kristoffer/test.txt

คุณจะได้รับ:

$0    # ocrscript.sh
$1    # -from
$2    # /home/kristoffer/test.png
$3    # -to
$4    # /home/kristoffer/test.txt

อาจเป็นการง่ายกว่าที่จะละเว้น-fromและ-toเช่น:

ocrscript.sh /home/kristoffer/test.png /home/kristoffer/test.txt

จากนั้นคุณจะมี:

$1    # /home/kristoffer/test.png
$2    # /home/kristoffer/test.txt

ข้อเสียคือคุณจะต้องจัดหาตามลำดับที่ถูกต้อง มีไลบรารีที่ช่วยให้สามารถแยกวิเคราะห์อาร์กิวเมนต์ที่มีชื่อบนบรรทัดคำสั่งได้ง่ายขึ้น แต่โดยปกติแล้วสำหรับเชลล์สคริปต์แบบธรรมดาคุณควรใช้วิธีง่ายๆหากไม่มีปัญหา

จากนั้นคุณสามารถทำได้:

/usr/local/bin/abbyyocr9 -rl Swedish -if "$1" -of "$2" 2>&1

เครื่องหมายคำพูดคู่รอบ$1และ$2ไม่จำเป็นเสมอไป แต่จะได้รับการแนะนำเนื่องจากบางสตริงจะไม่ทำงานหากคุณไม่ใส่ไว้ระหว่างเครื่องหมายคำพูดคู่


69

หากคุณไม่ได้ยึดติดกับการใช้ "from" และ "to" เป็นชื่อตัวเลือกของคุณอย่างสมบูรณ์มันค่อนข้างง่ายที่จะใช้สิ่งนี้โดยใช้getopts :

while getopts f:t: opts; do
   case ${opts} in
      f) FROM_VAL=${OPTARG} ;;
      t) TO_VAL=${OPTARG} ;;
   esac
done

getopts เป็นโปรแกรมที่ประมวลผลอาร์กิวเมนต์บรรทัดคำสั่งและแยกวิเคราะห์ให้คุณได้อย่างสะดวก

f:t:ระบุว่าคุณต้องการพารามิเตอร์ 2 ตัวที่มีค่า (ระบุด้วยเครื่องหมายจุดคู่) สิ่งที่ต้องการf:t:vบอกว่า-vจะถูกตีความว่าเป็นธงเท่านั้น

optsเป็นที่เก็บพารามิเตอร์ปัจจุบัน caseคำสั่งเป็นที่ที่คุณจะดำเนินการนี้

${OPTARG}มีค่าตามหลังพารามิเตอร์ ${FROM_VAL}ตัวอย่างเช่นจะได้รับค่า/home/kristoffer/test.pngหากคุณเรียกใช้สคริปต์ของคุณเช่น:

ocrscript.sh -f /home/kristoffer/test.png -t /home/kristoffer/test.txt

ตามที่คนอื่นแนะนำหากนี่เป็นครั้งแรกของคุณในการเขียนสคริปต์ทุบตีคุณควรอ่านข้อมูลพื้นฐานบางอย่าง นี่เป็นเพียงบทแนะนำสั้น ๆ เกี่ยวกับวิธีการgetoptsทำงาน


1
นี่ดูเหมือนจะเป็นวิธีแก้ปัญหาที่อ่านได้ แล้วคุณจะระบุสองแฟล็กได้อย่างไร?
Zelphir Kaltstahl

@ Zelphir คุณสามารถระบุแฟล็กตั้งแต่สองแฟล็กขึ้นไปเพียงแค่เลือก ":" หลังแฟล็ก ตัวอย่างเช่นf:t:vsจะเป็น-f some_f -t some_t -v -s
h_s

35

ใช้ตัวแปร"$1", "$2", "$3"และอื่น ๆ เพื่อการเข้าถึงข้อโต้แย้ง ในการเข้าถึงทั้งหมดคุณสามารถใช้"$@"หรือเพื่อรับจำนวนอาร์กิวเมนต์$#(อาจมีประโยชน์ในการตรวจสอบอาร์กิวเมนต์น้อยเกินไปหรือมากเกินไป)


24

ฉันต้องการตรวจสอบให้แน่ใจว่าสคริปต์ของฉันพกพาได้อย่างสมบูรณ์ระหว่างเครื่องต่างๆเชลล์และแม้แต่เวอร์ชัน cygwin นอกจากนี้เพื่อนร่วมงานของฉันซึ่งเป็นคนที่ฉันต้องเขียนสคริปต์เป็นโปรแกรมเมอร์ดังนั้นฉันจึงใช้สิ่งนี้:

for ((i=1;i<=$#;i++)); 
do

    if [ ${!i} = "-s" ] 
    then ((i++)) 
        var1=${!i};

    elif [ ${!i} = "-log" ];
    then ((i++)) 
        logFile=${!i};  

    elif [ ${!i} = "-x" ];
    then ((i++)) 
        var2=${!i};    

    elif [ ${!i} = "-p" ]; 
    then ((i++)) 
        var3=${!i};

    elif [ ${!i} = "-b" ];
    then ((i++)) 
        var4=${!i};

    elif [ ${!i} = "-l" ];
    then ((i++)) 
        var5=${!i}; 

    elif [ ${!i} = "-a" ];
    then ((i++)) 
        var6=${!i};
    fi

done;

เหตุผล: ฉันรวมlauncher.shสคริปต์ไว้ด้วยเนื่องจากการดำเนินการทั้งหมดมีหลายขั้นตอนซึ่งเสมือนเป็นอิสระต่อกัน (ฉันกำลังพูดว่า "เสมือน" เพราะแม้ว่าแต่ละสคริปต์จะทำงานได้ด้วยตัวเอง แต่ก็มักจะทำงานร่วมกันทั้งหมด ) และในสองวันฉันพบว่าประมาณครึ่งหนึ่งของเพื่อนร่วมงานของฉันซึ่งเป็นโปรแกรมเมอร์และทุกคนดีเกินกว่าที่จะใช้ไฟล์ตัวเรียกใช้งานติดตาม "การใช้งาน" หรืออ่าน HELP ที่แสดงทุกครั้งที่ทำอะไรบางอย่าง ผิดและพวกเขาทำให้เรื่องทั้งหมดยุ่งเหยิงเรียกใช้สคริปต์ที่มีข้อโต้แย้งผิดลำดับและบ่นว่าสคริปต์ทำงานไม่ถูกต้อง ในฐานะที่เป็นคนเจ้าอารมณ์ฉันตัดสินใจที่จะยกเครื่องสคริปต์ทั้งหมดของฉันเพื่อให้แน่ใจว่าพวกเขาพิสูจน์ได้ว่าเป็นเพื่อนร่วมงาน ส่วนโค้ดด้านบนเป็นสิ่งแรก


2
ฉันชอบสิ่งนี้. ฉันกำลังเพิ่มส่วนต่อท้าย `else echo" อาร์กิวเมนต์ไม่ถูกต้อง: $ {! i} "((i ++))
fi`

6

ใน bash $1คืออาร์กิวเมนต์แรกที่ส่งไปยังสคริปต์$2ที่สองและอื่น ๆ

/usr/local/bin/abbyyocr9 -rl Swedish -if "$1" -of "$2" 2>&1

คุณสามารถใช้:

./your_script.sh some_source_file.png destination_file.txt

คำอธิบายเกี่ยวกับเครื่องหมายคำพูดคู่

พิจารณาสามสคริปต์:

# foo.sh
bash bar.sh $1

# cat foo2.sh
bash bar.sh "$1"

# bar.sh
echo "1-$1" "2-$2"

ตอนนี้เรียกใช้:

$ bash foo.sh "a b"
1-a 2-b

$ bash foo2.sh "a b"
1-a b 2-

เมื่อคุณเรียกใช้foo.sh "a b"มันจะเรียกใช้bar.sh a b(สองอาร์กิวเมนต์) และด้วยfoo2.sh "a b"มันจะเรียกใช้bar.sh "a b"(1 อาร์กิวเมนต์) โปรดจำไว้เสมอว่าพารามิเตอร์ถูกส่งผ่านและขยายออกไปอย่างไรจะช่วยให้คุณปวดหัวได้มาก

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.