$#
adalah jumlah argumen, tetapi ingat itu akan berbeda dalam suatu fungsi.
$#
adalah jumlah parameter posisi yang diteruskan ke fungsi skrip, shell, atau shell . Ini karena, saat fungsi shell sedang berjalan, parameter posisi sementara diganti dengan argumen ke fungsi . Ini memungkinkan fungsi menerima dan menggunakan parameter posisinya sendiri.
Skrip ini selalu dicetak 3
, terlepas dari berapa banyak argumen yang diteruskan ke skrip itu sendiri, karena "$#"
dalam fungsinya f
memperluas ke jumlah argumen yang diteruskan ke fungsi:
#!/bin/sh
f() {
echo "$#"
}
f a b c
Ini penting karena ini berarti kode seperti ini tidak berfungsi seperti yang Anda harapkan, jika Anda tidak terbiasa dengan cara parameter posisi bekerja dalam fungsi shell:
#!/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...
Dalam check_args
, $#
memperluas ke jumlah argumen yang diteruskan ke fungsi itu sendiri, yang dalam skrip itu selalu 0.
Jika Anda ingin fungsi seperti itu dalam fungsi shell, Anda harus menulis sesuatu seperti ini sebagai gantinya:
#!/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 "$#"
Ini bekerja karena $#
diperluas di luar fungsi dan dilewatkan ke fungsi sebagai salah satu yang parameter posisi. Di dalam fungsi, $1
memperluas ke parameter posisi pertama yang dilewatkan ke fungsi shell, bukan ke skrip bagian itu.
Dengan demikian, seperti $#
, parameter khusus $1
, $2
, dll, serta $@
dan $*
, juga berkaitan dengan argumen dilewatkan ke fungsi, ketika mereka diperluas dalam fungsi. Namun, $0
tidak tidak berubah nama fungsi, itulah sebabnya saya masih bisa menggunakannya untuk menghasilkan pesan kesalahan kualitas.
$ ./check-args-demo a b c
./check-args-demo: error: need 2 arguments, got 3
Demikian pula, jika Anda mendefinisikan satu fungsi di dalam yang lain, Anda bekerja dengan parameter posisi yang diteruskan ke fungsi terdalam di mana ekspansi dilakukan:
#!/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
Saya menelepon skrip ini nested
dan (setelah menjalankan chmod +x nested
) saya menjalankannya:
$ ./nested a
script got 1 arguments
outer() got 2 arguments
inner() got 3 arguments
Ya saya tahu. "1 argumen" adalah bug pluralisasi.
Parameter posisi juga dapat diubah.
Jika Anda menulis skrip, parameter posisi di luar fungsi akan menjadi argumen baris perintah yang diteruskan ke skrip kecuali Anda telah mengubahnya .
Salah satu cara umum untuk mengubahnya adalah dengan shift
builtin, yang menggeser setiap parameter posisi ke kiri oleh satu, menjatuhkan yang pertama dan menurun $#
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".
Mereka juga dapat diubah dengan set
builtin:
#!/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
$#
? Apa yang ingin Anda capai? Di mana Anda mendapatkan perintah ini. Itu tidak relevan sama sekali.