Parameter skrip di Bash

103

Saya mencoba membuat skrip shell yang harus digunakan seperti ini:

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

Script tersebut kemudian akan mengubah file gambar menjadi file teks. Inilah yang saya dapatkan sejauh ini:

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

Tapi saya tidak tahu bagaimana mendapatkan the -fromand -tovalues. Ada ide tentang bagaimana melakukannya?

Kristoffer
sumber
6
Anda harus membaca tldp.org/LDP/Bash-Beginners-Guide/html/…
Mehul Rathod

Jawaban:

124

Argumen yang Anda berikan kepada bashscript akan muncul dalam variabel $1dan $2dan $3di mana angka menunjukkan argumen. $0adalah perintah itu sendiri.

Argumen dipisahkan oleh spasi, jadi jika Anda memberikan -fromdan -topada perintah, mereka akan berakhir di variabel ini juga, jadi untuk ini:

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

Anda akan mendapatkan:

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

Mungkin lebih mudah untuk menghilangkan -fromdan -to, seperti:

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

Kemudian Anda akan memiliki:

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

Sisi negatifnya adalah Anda harus memasoknya dengan urutan yang benar. Ada pustaka yang dapat mempermudah penguraian argumen bernama pada baris perintah, tetapi biasanya untuk skrip shell sederhana Anda sebaiknya menggunakan cara mudah, jika tidak ada masalah.

Kemudian Anda dapat melakukan:

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

Tanda kutip ganda di sekitar $1dan $2tidak selalu diperlukan tetapi disarankan, karena beberapa string tidak akan berfungsi jika Anda tidak meletakkannya di antara tanda kutip ganda.

gitaarik
sumber
69

Jika Anda tidak sepenuhnya terikat untuk menggunakan "dari" dan "ke" sebagai nama opsi Anda, cukup mudah untuk menerapkannya menggunakan getopts :

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

getopts adalah program yang memproses argumen baris perintah dan dengan mudah menguraikannya untuk Anda.

f:t:menentukan bahwa Anda mengharapkan 2 parameter yang berisi nilai (ditunjukkan dengan titik dua). Sesuatu seperti f:t:vmengatakan itu -vhanya akan diartikan sebagai bendera.

optsadalah tempat parameter saat ini disimpan. The casepernyataan adalah di mana Anda akan memproses ini.

${OPTARG}berisi nilai yang mengikuti parameter. ${FROM_VAL}Misalnya akan mendapatkan nilai /home/kristoffer/test.pngjika Anda menjalankan skrip Anda seperti:

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

Seperti yang disarankan orang lain, jika ini adalah pertama kalinya Anda menulis skrip bash, Anda harus benar-benar membaca tentang beberapa dasar. Ini hanyalah tutorial singkat tentang cara getoptskerjanya.

Manny D
sumber
1
Ini sepertinya solusi yang bisa dibaca. Bagaimana Anda menentukan dua bendera?
Zelphir Kaltstahl
@Zelphir, Anda dapat menetapkan dua atau lebih panji hanya dengan menghilangkan ":" setelah panji. Misalnya f:t:vsakan-f some_f -t some_t -v -s
h_s
34

Menggunakan variabel "$1", "$2", "$3"dan sebagainya untuk argumen akses. Untuk mengakses semuanya, Anda dapat menggunakan "$@", atau untuk menghitung argumen $#(mungkin berguna untuk memeriksa terlalu sedikit atau terlalu banyak argumen).

StianE
sumber
24

Saya perlu memastikan bahwa skrip saya sepenuhnya portabel di antara berbagai mesin, shell, dan bahkan versi cygwin. Lebih jauh, rekan-rekan saya yang harus saya tulis skripnya, adalah programmer, jadi saya akhirnya menggunakan ini:

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;

Rasional: Saya menyertakan launcher.shskrip juga, karena keseluruhan operasi memiliki beberapa langkah yang semu independen satu sama lain (saya katakan "kuasi", karena meskipun setiap skrip dapat dijalankan sendiri-sendiri, biasanya semuanya dijalankan bersama ), dan dalam dua hari saya menemukan, bahwa sekitar setengah dari kolega saya, sebagai pemrogram dan semuanya, terlalu baik untuk menggunakan file peluncur, mengikuti "penggunaan", atau membaca BANTUAN yang ditampilkan setiap kali mereka melakukan sesuatu salah dan mereka mengacaukan semuanya, menjalankan skrip dengan argumen dalam urutan yang salah dan mengeluh bahwa skrip tidak berfungsi dengan baik. Menjadi orang yang mudah tersinggung, saya memutuskan untuk merombak semua skrip saya untuk memastikan bahwa itu adalah bukti kolega. Segmen kode di atas adalah yang pertama.

pengguna1628658
sumber
2
Saya suka ini. Saya menambahkan bagian di akhir `else echo" Argumen tidak valid: $ {! I} "((i ++))
fi`
6

Dalam bash $1adalah argumen pertama yang diteruskan ke skrip, $2kedua dan seterusnya

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

Jadi Anda bisa menggunakan:

./your_script.sh some_source_file.png destination_file.txt

Penjelasan tentang tanda kutip ganda;

pertimbangkan tiga skrip:

# foo.sh
bash bar.sh $1

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

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

Sekarang panggil:

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

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

Ketika Anda memanggil foo.sh "a b"maka itu memanggil bar.sh a b(dua argumen), dan dengan foo2.sh "a b"itu memanggil bar.sh "a b"(1 argumen). Selalu ingat bagaimana parameter dilewatkan dan diperluas dalam bash, itu akan menghemat banyak sakit kepala.

Jakub M.
sumber