Bir işlevin içinde arayanın komut satırı argümanlarına nasıl erişilir?


102

Bash'de komut dosyalarının komut satırı argümanlarına erişecek bir fonksiyon yazmaya çalışıyorum, ancak bunlar fonksiyonun konumsal argümanlarıyla değiştirildi. Açıkça iletilmezlerse, işlevin komut satırı argümanlarına erişmesinin bir yolu var mı?

# Demo function
function stuff {
  echo $0 $*
}

# Echo's the name of the script, but no command line arguments
stuff

# Echo's everything I want, but trying to avoid
stuff $*

3
Kafam biraz karıştı, argümanların onları geçmesini istemiyor musun?
Ravi Vyas

4
Evet, önemli olan, komut satırı argümanlarını bir fonksiyonun içinden fonksiyonel argümanlar olarak iletmeden almaktır. İşleve aktarılan argümanlardan bağımsız olarak komut satırı argümanlarına dayalı olarak hata işleme yapmak istediğim bir hata işleme durumu ile ilgisi var.
DonGar

Bilginize, $*son derece hatalı olduğunu - bu değiştireceğiz ./yourScript "first argument" "second argument"için ./yourscript "first" "argument" "second" "argument", veya değiştirmek ./yourscript '*.txt'gibi bir şeye ./yourscript one.txt two.txttırnak rağmen.
Charles Duffy

Yanıtlar:


48

Bash ref el kitabını okudum, "yığın" hakkında çok konuşulmasına rağmen, bu şeyin BASH_ARGV'de yakalandığını söylüyor.

#!/bin/bash

function argv {
    for a in ${BASH_ARGV[*]} ; do
      echo -n "$a "
    done
    echo
}

function f {
    echo f $1 $2 $3
    echo -n f ; argv
}

function g {
    echo g $1 $2 $3
    echo -n g; argv
    f
}

f boo bar baz
g goo gar gaz

F.sh olarak kaydedin

$ ./f.sh arg0 arg1 arg2
f boo bar baz
farg2 arg1 arg0 
g goo gar gaz
garg2 arg1 arg0 
f
farg2 arg1 arg0 

5
Diziyi bu şekilde değiştirmenin bağımsız değişkenlerin komut satırından ters sırada olmasına neden olduğunu unutmayın.
Andrew Backer

97

Bağımsız değişkenlerinizin C stiline sahip olmasını istiyorsanız (bağımsız değişkenler dizisi + bağımsız değişken sayısı) $@ve kullanabilirsiniz $#.

$#size argümanların sayısını verir.
$@size tüm argümanları verir. Bunu bir diziye dönüştürebilirsiniz.args=("$@") .

Yani mesela:

args=("$@")
echo $# arguments passed
echo ${args[0]} ${args[1]} ${args[2]}

Burada ${args[0]}aslında 1. argüman olduğunu ve betiğinizin adı olmadığını unutmayın.


5
Bu soruya hitap etmiyor - komut satırı argümanlarını bir kabuk işlevine iletmeyi soruyor.
Cascabel

6
@Jefromi, aslında soruyu mükemmel yanıtlıyor. argsÖnceden açıklandığı gibi başlatırsanız, diziyi bir işlevin içinden kullanabilirsiniz .
vadipp

1
Bunu argümanlar üzerinde yinelemekten çok daha temiz buluyorum.
Félix Gagnon-Grenier

1
Bu basit ve kolaydır. Mükemmel cevap. Bunu 7 yıldan uzun bir süre önce yayınladınız, gelecekten merhaba: Temmuz 2017
SDsolar

Daha da iyisi gibi alıntı yapmaktır echo "${args[0]} ${args[1]} ${args[2]}", aksi takdirde argümanlar dosya adı genişlemesine tabidir.
Benjamin W.

18
#!/usr/bin/env bash

echo name of script is $0
echo first argument is $1
echo second argument is $2
echo seventeenth argument is $17
echo number of arguments is $#

Düzenleme: lütfen soru hakkındaki yorumuma bakın


17

Ravi'nin yorumu esasen cevaptır. Fonksiyonlar kendi argümanlarını alır. Bunların komut satırı argümanlarıyla aynı olmasını istiyorsanız, bunları iletmelisiniz. Aksi takdirde, açıkça argümansız bir işlevi çağırırsınız.

Bununla birlikte, komut satırı bağımsız değişkenlerini diğer işlevler içinde kullanmak için genel bir dizide depolamak isterseniz yapabilirsiniz:

my_function() {
    echo "stored arguments:"
    for arg in "${commandline_args[@]}"; do
        echo "    $arg"
    done
}

commandline_args=("$@")

my_function

Sen aracılığıyla komut satırı argümanları erişmek zorunda commandline_argsdeğil, değişken $@, $1,$2 vb, ancak uygun olduğunda. Doğrudan argüman dizisine atamanın herhangi bir yolunun farkında değilim, ancak birisi biliyorsa, lütfen beni aydınlatın!

Ayrıca, kullandığım ve alıntı yaptığım yönteme dikkat edin $@- bu, özel karakterlerin (beyaz boşluk) karıştırılmamasını sağlama yöntemidir .


6
# Save the script arguments
SCRIPT_NAME=$0
ARG_1=$1
ARGS_ALL=$*

function stuff {
  # use script args via the variables you saved
  # or the function args via $
  echo $0 $*
} 


# Call the function with arguments
stuff 1 2 3 4

2

Böyle de yapılabilir

#!/bin/bash
# script_name function_test.sh
function argument(){
for i in $@;do
    echo $i
done;
}
argument $@

Şimdi senaryonuzu şöyle arayın

./function_test.sh argument1 argument2

function print() {iki farklı işlev bildirim formu arasındaki bir birleşmedir - function print {bu, bash'nin POSIX öncesi (yani 1991 öncesi) ksh ile geriye dönük uyumluluk için desteklediği eski ksh sözdizimidir ve print() {POSIX standardize edilmiştir. Diğer mermilerle daha geniş uyumluluk için birini veya diğerini kullanmayı düşünün; ayrıca bkz. wiki.bash-hackers.org/scripting/obsolete
Charles Duffy

1

Bunları yinelemek için shift anahtar sözcüğünü (operatör?) Kullanabilirsiniz. Misal:

#!/bin/bash
function print()
{
    while [ $# -gt 0 ]
    do
        echo $1;
        shift 1;
    done
}
print $*;

2
function print() {iki farklı işlev bildirim formu arasındaki bir birleşmedir - function print {bu, bash'nin POSIX öncesi (yani 1991 öncesi) ksh ile geriye dönük uyumluluk için desteklediği eski ksh sözdizimidir ve print() {POSIX standardize edilmiştir. Diğer mermilerle daha geniş uyumluluk için birini veya diğerini kullanmayı düşünün; ayrıca bkz. wiki.bash-hackers.org/scripting/obsolete
Charles Duffy

1

Çözümüm:

Şunun gibi herhangi bir argüman iletmeden diğer tüm işlevlerden daha önce çağrılan bir işlev betiği oluşturun:

! / bin / bash

işlev init () {ORIGOPT = "- $ @ -"}

Ayrıca, init'i çağırıp ORIGOPT varlığını gerektiği gibi kullanabilirsiniz, artı olarak, her zaman yeni bir var atarım ve ORIGOPT'un içeriğini yeni işlevlerimde kopyalarım, böylece kimsenin ona dokunmayacağından emin olabilirsiniz veya değiştir.

'Sed -E' ile ayrıştırmayı kolaylaştırmak için boşluklar ve çizgiler ekledim, ayrıca bash bunu referans olarak geçirmeyecek ve işlevler daha fazla argümanla çağrıldıkça ORIGOPT'u büyütecek.

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.