Getopts ile hiçbir seçeneğin geçilmediğini nasıl tespit edebilirim?


19

Bu kod var -

#getoptDemo.sh
usage()
{
    echo "usage: <command> options:<w|l|h>"
}
while getopts wlh: option
do
    case $option in
            (w)
                    name='1';;
            (l)
                    name='2';;
            (h)
                    name='3';;
            (*)
                    usage
                    exit;;
    esac
done
print 'hi'$name

Çalıştığımda bash getoptDemos.sh(seçenek olmadan) hiişlevi çağırmak yerine yazdırır usage. W, h ve l dışında seçenekler verildiğinde kullanımı çağırır. Hiçbir seçenek belirtilmediğinde çalışmaz.

Ben kullanarak denedi ?, \?, :yerine *ama istediğini elde edemez. Demek istediğim her şey kullanmak docsiçin getoptdiyor ?.

Neyi yanlış yapıyorum?


Hangi kabuğu altında çalıştırıyorsunuz?
Julian

Ben altında koşuyorum/bin/bash
Hussain Tamboli

Yanıtlar:


15

Bu komut dosyasını herhangi bir seçenek olmadan çalıştırdığınızda, getopt false değerini döndürür, bu nedenle döngüye hiç girmez. Sadece baskıya düşecek - bu ksh / zsh mı?

Bir seçeneğiniz olması gerekiyorsa, en iyisi döngüden sonra $ adını test etmektir.

if [ -z "$name" ]
then
   usage
   exit
fi

Ancak $namearamadan önce boş olduğundan emin olun getopts( $namekabukta başlangıçta alınan bir ortamda olabilir )

unset name

( getoptsdöngüden önce )


Hayır. onun bash. Öyleyse istediğimi nasıl elde edebilirim - no argumentbash kullanarak durumu ele alın .
Hussain Tamboli

Zorunlu bir seçenek istiyorsanız, bu mümkün olduğunu düşünmüyorum - muhtemelen neden denir? :) Döngünden sonra ayarlandığından emin olmak için $ name olsa da test edebilirsiniz. eğer [-z "$ name"]; sonra kullanım; çıkış ; fi
Julian

Teşekkürler. Yukarıdaki kod gerçekten yardımcı oldu. Çok kötü bir getoptshükmü yok. Bundan daha kötüsü seni oylayamaz.
Hussain Tamboli

başka bir kabuk çalıştırıyor olsaydım? zsh, sh. bash dışında herhangi bir kabuk bu duruma dikkat eder mi?
Hussain Tamboli

20

getoptsseçenekleri sırayla işler. Bu onun işi. Kullanıcı hiçbir seçeneği geçemezse, ilk çağırma getoptswhile döngüsünden çıkar.

Seçeneklerin hiçbiri bağımsız değişken almazsa, değerinin değeri OPTINDkaç seçeneğin geçirildiğini belirtir. Genel olarak, OPTINDseçenek olmayan argümanların (işlenenler) aksine, seçenek veya seçenek argümanı olan argüman sayısıdır.

while getopts …; do …; done
if [ $OPTIND -eq 1 ]; then echo "No options were passed"; fi
shift $((OPTIND-1))
echo "$# non-option arguments"

Her durumda, seçenek olup olmadığını belirlemeye çalışmıyorsunuz, ancak name-setting seçeneklerinin hiçbirinin geçip geçmediğini belirlemeye çalışmıyorsunuz. Bu yüzden ayarlanmamış olup olmadığını kontrol edin name(ve önce ayarlamamasına dikkat edin) .


1
Teşekkürler. Sizin için +1. kodunuzdaki son 3 satırı sample.sh dosyasına koyduğumda ve çalıştırdığımda bash sample.sh -abc file.txt- verir 1 non-option arguments. kaç seçeneğin verildiğini nasıl öğrenebilirim? (burada 3)
Hussain Tamboli

1
Tuhaf kimse bu hafif hata hakkında yorum yapmadı - eğer herhangi bir seçenek verilmezse, OPTIND 'getopts ...' döngüsünden sonra 1 olacaktır. Bu nedenle, eğer kontrol eşitliği sıfır ile değil 1 ile kontrol etmelidir.
Daniel

4

Komut dosyanızın seçenek bağımsız değişkenleri alması gerekiyorsa, bu bloğu başına (getops'dan önce) yerleştirin.

if [[ ! $@ =~ ^\-.+ ]]
then
  #display_help;
fi

Block, parametre dizesinin -sembolle başlamamasını denetler; bu, ilk parametrenin bir seçenek bağımsız değişkeni olmadığını gösterir.


2

Bir değişkenle kontrol ederdim. Getopts hiçbir argüman olmaması durumunda döngüyü asla geçemezse, bunu örneğin şöyle kullanabilirsiniz:

#getoptDemo.sh
usage()
{
    echo "usage: <command> options:<w|l|h>"
}

no_args="true"
while getopts wlh: option
do
    case $option in
            (w)
                    name='1';;
            (l)
                    name='2';;
            (h)
                    name='3';;
            (*)
                    usage
                    exit;;
    esac
    no_args="false"
done

[[ "$no_args" == "true" ]] && { usage; exit 1; }

print 'hi'$name

0

Bloğunuzdan hemen önce (komut satırında ilettiğiniz ilk bağımsız değişken / seçenek) boş bir dizeye eşit getoptsolup olmadığını kontrol edin $1. Öyleyse, kullanım mesajını yazdırın ve çıkın (veya anarşistseniz "seçenek yok" işlevini yürütün), aksi takdirde getoptsnormal gibi seçenekleri ayrıştırın.

Bu özelliğin getopts'a dahil edilmemesinin nedeni, zaten "if-else" ile bash'da başarabilmenizdir. Misal:

if [[ $1 == "" ]]; then
    Your_Usage_Function;
    exit;
else
   #parse options with getopts code block here;
fi

Mantıklı olmak?

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.