Jawaban singkat: gunakan"$@"
(perhatikan tanda kutip ganda). Bentuk-bentuk lain sangat jarang berguna.
"$@"
adalah sintaks yang agak aneh. Itu digantikan oleh semua parameter posisi, sebagai bidang yang terpisah. Jika tidak ada parameter posisional ( $#
0), maka "$@"
ekspansi menjadi nol (bukan string kosong, tetapi daftar dengan 0 elemen), jika ada satu parameter posisional maka "$@"
sama dengan "$1"
, jika ada dua parameter posisional maka "$@"
setara dengan "$1" "$2"
, dll.
"$@"
memungkinkan Anda untuk meneruskan argumen skrip atau fungsi ke perintah lain. Ini sangat berguna untuk pembungkus yang melakukan hal-hal seperti mengatur variabel lingkungan, menyiapkan file data, dll. Sebelum memanggil perintah dengan argumen dan opsi yang sama dengan pembungkus dipanggil.
Misalnya, fungsi berikut memfilter output dari cvs -nq update
. Terlepas dari pemfilteran output dan status pengembalian (yang grep
bukan dari itu cvs
), memanggil cvssm
beberapa argumen berperilaku seperti memanggil cvs -nq update
dengan argumen ini.
cvssm () { cvs -nq update "$@" | egrep -v '^[?A]'; }
"$@"
memperluas ke daftar parameter posisi. Dalam shell yang mendukung array, ada sintaksis yang sama untuk memperluas ke daftar elemen array: "${array[@]}"
(kawat gigi wajib diisi kecuali di zsh). Sekali lagi, tanda kutip ganda agak menyesatkan: mereka melindungi terhadap pemisahan bidang dan pembuatan pola elemen array, tetapi setiap elemen array berakhir di bidangnya sendiri.
Beberapa cangkang kuno memiliki apa yang bisa dibilang bug: ketika tidak ada argumen posisional, "$@"
diperluas ke bidang tunggal yang berisi string kosong, bukannya ke bidang tidak ada. Ini mengarah pada solusi${1+"$@"}
(dibuat terkenal melalui dokumentasi Perl ). Hanya versi yang lebih lama dari shell Bourne aktual dan implementasi OSF1 yang terpengaruh, tidak ada penggantian yang kompatibel modern (abu, ksh, bash, ...). /bin/sh
tidak terpengaruh pada sistem apa pun yang dirilis pada abad ke-21 yang saya tahu (kecuali jika Anda menghitung rilis pemeliharaan Tru64, dan bahkan ada /usr/xpg4/bin/sh
yang aman sehingga hanya #!/bin/sh
skrip yang terpengaruh, bukan #!/usr/bin/env sh
skrip selama PATH Anda diatur untuk kepatuhan POSIX) . Singkatnya, ini adalah anekdot sejarah yang tidak perlu Anda khawatirkan.
"$*"
selalu mengembang menjadi satu kata. Kata ini berisi parameter posisi, disatukan dengan spasi di antaranya. (Lebih umum, pemisah adalah karakter pertama dari nilai IFS
variabel. Jika nilai IFS
adalah string kosong, pemisah adalah string kosong.) Jika tidak ada parameter posisi maka "$*"
string kosong, jika ada dua parameter posisi dan IFS
memiliki nilai standarnya kemudian "$*"
setara dengan "$1 $2"
, dll.
$@
dan $*
kutipan luar sama. Mereka memperluas ke daftar parameter posisi, sebagai bidang yang terpisah, seperti "$@"
; tetapi setiap bidang yang dihasilkan kemudian dibagi menjadi bidang-bidang terpisah yang diperlakukan sebagai pola wildcard nama file, seperti biasa dengan ekspansi variabel yang tidak dikutip.
Misalnya, jika direktori saat ini berisi tiga file bar
, baz
dan foo
, maka:
set -- # no positional parameters
for x in "$@"; do echo "$x"; done # prints nothing
for x in "$*"; do echo "$x"; done # prints 1 empty line
for x in $*; do echo "$x"; done # prints nothing
set -- "b* c*" "qux"
echo "$@" # prints `b* c* qux`
echo "$*" # prints `b* c* qux`
echo $* # prints `bar baz c* qux`
for x in "$@"; do echo "$x"; done # prints 2 lines: `b* c*` and `qux`
for x in "$*"; do echo "$x"; done # prints 1 lines: `b* c* qux`
for x in $*; do echo "$x"; done # prints 4 lines: `bar`, `baz`, `c*` and `qux`