$# bağımsız değişkenlerin sayısıdır, ancak bir işlevde farklı olacağını unutmayın.
$#komut dosyası, kabuk veya kabuk işlevine iletilen konumsal parametrelerin sayısıdır . Bunun nedeni, bir kabuk işlevi çalışırken, konum parametrelerinin geçici olarak işlevin argümanları ile değiştirilmiş olmasıdır . Bu, fonksiyonların kendi konum parametrelerini kabul etmesini ve kullanmasını sağlar.
Bu komut dosyası 3, komut dosyasında kaç tane argüman kullanıldığına bakılmaksızın her zaman yazdırılır , çünkü "$#"işlevde işleve fverilen argüman sayısına genişler:
#!/bin/sh
f() {
echo "$#"
}
f a b c
Bu önemlidir, çünkü konum parametrelerinin kabuk işlevlerinde nasıl çalıştığını bilmiyorsanız, böyle bir kodun beklediğiniz gibi çalışmadığı anlamına gelir:
#!/bin/sh
check_args() { # doesn't work!
if [ "$#" -ne 2 ]; then
printf '%s: error: need 2 arguments, got %d\n' "$0" "$#" >&2
exit 1
fi
}
# Maybe check some other things...
check_args
# Do other stuff...
Içinde check_args, $#bu betiğin içinde her zaman 0 olan fonksiyonun kendisine iletilen argümanların sayısına genişler.
Bir kabuk işlevinde bu tür bir işlevsellik istiyorsanız, bunun yerine böyle bir şey yazmanız gerekir:
#!/bin/sh
check_args() { # works -- the caller must pass the number of arguments received
if [ "$1" -ne 2 ]; then
printf '%s: error: need 2 arguments, got %d\n' "$0" "$1" >&2
exit 1
fi
}
# Maybe check some other things...
check_args "$#"
Bunun nedeni çalışır $#genişletilir dışında fonksiyonu ve biri olarak işleve iletilen onun konumsal parametreler. İşlev içinde, $1parçası olduğu komut dosyası yerine kabuk işlevine geçirilen ilk konumsal parametreye genişler.
Böylece gibi $#, özel parametreler $1, $2vs., hem de $@ve $*, aynı zamanda fonksiyon genişletilmiş bir işleve geçirilen bağımsız değişkenler, aittir. Ancak, $0yok değil hala kaliteli bir hata mesajı üretmek için kullanmak başardı yüzden fonksiyonun ismine değiştirin.
$ ./check-args-demo a b c
./check-args-demo: error: need 2 arguments, got 3
Benzer şekilde, bir işlevi diğerinin içinde tanımlarsanız, genişlemenin gerçekleştirildiği en içteki işleve iletilen konumsal parametrelerle çalışıyorsunuz:
#!/bin/sh
outer() {
inner() {
printf 'inner() got %d arguments\n' "$#"
}
printf 'outer() got %d arguments\n' "$#"
inner x y z
}
printf 'script got %d arguments\n' "$#"
outer p q
Bu betiği aradım nestedve (çalıştırdıktan sonra chmod +x nested) koştum:
$ ./nested a
script got 1 arguments
outer() got 2 arguments
inner() got 3 arguments
Evet biliyorum. "1 argüman" çoğullaştırma hatası.
Konumsal parametreler de değiştirilebilir.
Bir komut dosyası yazıyorsanız, bir işlevin dışındaki konumsal parametreler siz değiştirmediğiniz sürece komut dosyasına iletilen komut satırı argümanları olacaktır .
Bunları değiştirmenin yaygın bir yolu shift, her bir konumsal parametreyi bir sola kaydırıp, ilkini düşürerek $#ve 1:
#!/bin/sh
while [ "$#" -ne 0 ]; do
printf '%d argument(s) remaining.\nGot "%s".\n\n' "$#" "$1"
shift
done
$ ./do-shift foo bar baz # I named the script do-shift.
3 argument(s) remaining.
Got "foo".
2 argument(s) remaining.
Got "bar".
1 argument(s) remaining.
Got "baz".
setYerleşik ile de değiştirilebilirler :
#!/bin/sh
printf '%d args: %s\n' "$#" "$*"
set foo bar baz
printf '%d args: %s\n' "$#" "$*"
$ ./set-args a b c d e # I named the script set-args.
5 args: a b c d e
3 args: foo bar baz
$#? Ne elde etmek istiyorsun? Bu komutu nereden aldın? Hiç alakalı değil.