Kabuk betiklerine adlandırılmış değişkenleri iletme


114

Adlandırılmış parametreleri bir kabuk betiğine iletmenin (kolay) bir yolu var mı?

Örneğin,

my_script -p_out '/some/path' -arg_1 '5'

Ve içeride my_script.shonları alırsınız:

# I believe this notation does not work, but is there anything close to it?
p_out=$ARGUMENTS['p_out']
arg1=$ARGUMENTS['arg_1']

printf "The Argument p_out is %s" "$p_out"
printf "The Argument arg_1 is %s" "$arg1"

Bu Bash veya Zsh'de mümkün mü?


2
docopt'a bir göz atın - adlandırılmış parametrelere yardımcı olur ve girdi doğrulamasını da yapar
Beat

Yanıtlar:


34

Muhtemelen en yakın sözdizimi:

p_out='/some/path' arg_1='5' my_script

7
Bununla ilgili, -kseçenek arama kabuğunda ayarlanmışsa my_script p_out='/some/path' arg_1='5', aynı etkiye sahiptir. (Atama şeklindeki tüm argümanlar çevreye, yalnızca komuttan önceki atamalar değil, eklenir.)
chepner

13
Bu sözdizimini çok severdim, ama BÜYÜK bir uyarıya sahipti: komut / işlev yürütmesinden sonra bu değişkenler hala geçerli kapsamda tanımlanacak! Örn: x=42 echo $x; echo $xBir sonraki çalıştırmada , ihmal my_scriptedilirse p_out, son kez geçen değere bağlı kalacaktır demektir! ( '/some/path')
Lucas Cimon

@LucasCimon unsetİlk çalıştırmadan sonra onları bir sonraki çalıştırmadan önce sıfırlayamaz mısınız?
Nikos Alexandris

2
@LucasCimon Bu doğru değil. x=42 echo $xdaha $xönce tanımlanmadıysa bile hiçbir şey çıkarmaz .
Hauke,

Haklısın @HaukeLaging, düzeltdiğiniz için teşekkürler
Lucas Cimon

148

Örneğin, tek harfli argüman adları ile sınırlı olmanın sakıncası yoksa my_script -p '/some/path' -a5, bash içerisinde getoptsörneğin

#!/bin/bash

while getopts ":a:p:" opt; do
  case $opt in
    a) arg_1="$OPTARG"
    ;;
    p) p_out="$OPTARG"
    ;;
    \?) echo "Invalid option -$OPTARG" >&2
    ;;
  esac
done

printf "Argument p_out is %s\n" "$p_out"
printf "Argument arg_1 is %s\n" "$arg_1"

O zaman yapabilirsin

$ ./my_script -p '/some/path' -a5
Argument p_out is /some/path
Argument arg_1 is 5

Yararlı bir küçük getopts öğretici var veya help getoptskabuk isteminde yazabilirsiniz .


25
Bu kabul edilen cevap olmalıdır
Kaushik Ghose

3
Bunun biraz eski olduğunu biliyorum, ama neden argümanlar için sadece 1 harf?
Kevin

1
Bunu uyguladım (ancak ive ile d). Çalıştığım zaman argüman my_script -i asd -d asdiçin boş bir dize alıyorum d. Çalıştırdığımda my_script -d asd -i asdher iki argüman için boş dizgi alıyorum.
Milkncookiez

3
@Milkncookiez - Benzer bir problemim vardı - Son tartışmadan sonra bir ':' eklemedim (benim durumumda 'w'). ':'
Derek

37

Bunu drupal.org'dan çaldım , ama böyle bir şey yapabilirsin:

while [ $# -gt 0 ]; do
  case "$1" in
    --p_out=*)
      p_out="${1#*=}"
      ;;
    --arg_1=*)
      arg_1="${1#*=}"
      ;;
    *)
      printf "***************************\n"
      printf "* Error: Invalid argument.*\n"
      printf "***************************\n"
      exit 1
  esac
  shift
done

Tek uyarı, sözdizimini kullanmanız gerektiğidir my_script --p_out=/some/path --arg_1=5.


7
İhtar gerekli değildir. :) Aşağıdaki koşullara sahip olabilirsiniz:-c|--condition)
Milkncookiez

28

Bu betiği kullanıyorum ve cazibe gibi çalışıyorum:

for ARGUMENT in "$@"
do

    KEY=$(echo $ARGUMENT | cut -f1 -d=)
    VALUE=$(echo $ARGUMENT | cut -f2 -d=)   

    case "$KEY" in
            STEPS)              STEPS=${VALUE} ;;
            REPOSITORY_NAME)    REPOSITORY_NAME=${VALUE} ;;     
            *)   
    esac    


done

echo "STEPS = $STEPS"
echo "REPOSITORY_NAME = $REPOSITORY_NAME"

kullanım

bash my_scripts.sh  STEPS="ABC" REPOSITORY_NAME="stackexchange"

Konsol sonucu:

STEPS = ABC
REPOSITORY_NAME = stackexchange

STEPS ve REPOSITORY_NAME , komut dosyasında kullanıma hazır.

Argümanların hangi sırada olduğu önemli değil.


4
Bu temiz ve kabul edilen cevap olmalıdır.
miguelmorin

15

Bununla birlikte zshkullanırsınız zparseopts:

#! /bin/zsh -
zmodload zsh/zutil
zparseopts -A ARGUMENTS -p_out: -arg_1:

p_out=$ARGUMENTS[--p_out]
arg1=$ARGUMENTS[--arg_1]

printf 'Argument p_out is "%s"\n' "$p_out"
printf 'Argument arg_1 is "%s"\n' "$arg_1"

Ama senaryoyu ararsın myscript --p_out foo.

zparseoptsUzun seçenekleri veya --p_out=fooGNU gibi bir sözdizimini kısaltmayı desteklemediğini unutmayın getopt(3).


Zparseopların neden argümanlar için sadece bir çizgi kullandıklarını biliyor musunuz []? Anlamsız!
Timo

@Timo, info zsh zparseoptsdetaylı bilgi için bakın
Stéphane Chazelas

9

Ben sadece bu senaryo ile geldi

while [ $# -gt 0 ]; do

   if [[ $1 == *"--"* ]]; then
        v="${1/--/}"
        declare $v="$2"
   fi

  shift
done

gibi my_script --p_out /some/path --arg_1 5ve sonra komut dosyasında $arg_1ve kullanabilirsiniz kullanabilirsiniz $p_out.


KSH88'deki bu çözümü sevdim v=``echo ${1} | awk '{print substr($1,3)}'`` typeset $v="$2"(Her iki tarafa da bir sırt bastır )
hol

-2

Bir işlev veya uygulama sıfırdan fazla argüman içeriyorsa, her zaman son bir argüman olur.

Seçenek işaretini ve değer çiftlerini aşağıdaki gibi okumak istiyorsanız: $ ./t.sh -o output -i input -l last

Değişken sayıda seçenek / değer çifti kabul etmek istiyorsanız,

Ve büyük istemiyorsanız "eğer .. o zaman .. başka .. fi" ağacı,

Ardından sıfır olmayan ve hatta argüman sayımını kontrol ettikten sonra,

Gövde olarak bu dört değerlendirme ifadesi ile bir süre döngüsü yazın, ardından döngüden geçen her geçişte belirlenen iki değeri kullanarak bir vaka ifadesi izleyin.

Kodlamanın zor kısmı burada gösterilmektedir:

#!/bin/sh    

# For each pair - this chunk is hard coded for the last pair.
eval TMP="'$'$#"
eval "PICK=$TMP"
eval TMP="'$'$(($#-1))"
eval "OPT=$TMP"

# process as required - usually a case statement on $OPT
echo "$OPT \n $PICK"

# Then decrement the indices (as in third eval statement) 

:<< EoF_test
$ ./t.sh -o output -i input -l last
-l 
last
$ ./t.sh -o output -l last
-l 
last
$ ./t.sh  -l last
-l 
last
EoF_test

-3
mitsos@redhat24$ my_script "a=1;b=mitsos;c=karamitsos"
#!/bin/sh
eval "$1"

komut dosyası kapsamı içine komut satırı parametrelerini enjekte ettiniz !!


3
Bu OP belirtilen sözdizimi ile çalışmıyor; istiyorlar-a 1 -b mitsos -c karamitsos
Michael Mrozek
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.