Apa arti $ @ dalam skrip shell?

Jawaban:

243

$@adalah semua parameter yang diteruskan ke skrip.

Misalnya, jika Anda menelepon ./someScript.sh foo barmaka $@akan sama dengan foo bar.

Jika kamu melakukan:

./someScript.sh foo bar

dan kemudian di dalam someScript.shreferensi:

umbrella_corp_options "$@"

ini akan diteruskan ke umbrella_corp_optionsdengan masing-masing parameter terlampir dalam tanda kutip ganda, yang memungkinkan untuk mengambil parameter dengan ruang kosong dari pemanggil dan meneruskannya.

Har
sumber
1
Apa yang akan $ $ berisi jika saya lakukan someScript.sh foo bar "boo far"?
trusktr
7
$ @ spesial jika ditulis dalam tanda kutip ganda. Maka akan menghasilkan daftar nilai yang dikutip, dalam kasus Anda, trusktr, dalam tiga argumen "foo", "bar", dan "boo far".
Alfe
4
Meskipun umumnya kasus, $@tidak belum tentu datang dari paramaters dilewatkan ke script ... misalnya; set a b "x   y"; printf '(%s)' "$@"output(a)(b)(x   y)
Peter.O
Saya suka jawaban Alfe lebih baik karena dia memberikan perbedaan utama antara $@dan$*
donleyp
106

$@hampir sama dengan $*, keduanya berarti "semua argumen baris perintah". Mereka sering digunakan untuk hanya meneruskan semua argumen ke program lain (sehingga membentuk pembungkus di sekitar program lain).

Perbedaan antara kedua sintaksis muncul ketika Anda memiliki argumen dengan spasi di dalamnya (misalnya) dan dimasukkan ke $@dalam tanda kutip ganda:

wrappedProgram "$@"
# ^^^ this is correct and will hand over all arguments in the way
#     we received them, i. e. as several arguments, each of them
#     containing all the spaces and other uglinesses they have.
wrappedProgram "$*"
# ^^^ this will hand over exactly one argument, containing all
#     original arguments, separated by single spaces.
wrappedProgram $*
# ^^^ this will join all arguments by single spaces as well and
#     will then split the string as the shell does on the command
#     line, thus it will split an argument containing spaces into
#     several arguments.

Contoh: Memanggil

wrapper "one two    three" four five "six seven"

akan menghasilkan:

"$@": wrappedProgram "one two    three" four five "six seven"
"$*": wrappedProgram "one two    three four five six seven"
                             ^^^^ These spaces are part of the first
                                  argument and are not changed.
$*:   wrappedProgram one two three four five six seven
Alfe
sumber
2
Mereka tidak sama, dan halaman manualnya jelas mengenai efek samping dari $ * menggunakan IFS — yang belum tentu ruang. (Jika mereka sama, tidak akan ada gunanya, selain kompatibilitas mungkin, dalam menawarkan keduanya.)
jørgensen
6
Tidak, mereka bukan. Dan saya mengatakan dua baris di bawah ini: "Perbedaan antara keduanya ..." Untuk mendapatkan kalimat pendek dan meningkatkan keterbacaan, pembaca harus membaca lebih dari satu kalimat sebelum memberikan vonis: - /
Alfe
2
Alfe, penyisipan Christoffer pada satu kata "hampir" membuat perbedaan besar, tanpa mengorbankan kesederhanaan atau keterbacaan. Sebenarnya saya menaikkan jawaban ini (sebagai lawan dari yang diterima) tepat karena penekanan perbedaan yang halus ... - sebelum menyadari bahwa itu hampir bertentangan dengan keinginan Anda! ;)
Sz.
Saya pikir kata itu membuat perbedaan besar bagi orang-orang yang memberikan vonis tepat setelah membaca kalimat pertama ;-) dan itu tidak pernah bertentangan dengan kehendak saya. Saya benar-benar ingin menulis juga untuk orang-orang ini.
Alfe
Sangat tidak jelas. wrappedProgram "$*"-> separated by single spaces.tetapi dalam contoh kedua Anda, mereka tidak dipisahkan oleh spasi tunggal.
Felix Dombek
36

Ini adalah argumen baris perintah di mana:

$@= menyimpan semua argumen dalam daftar string
$*= menyimpan semua argumen sebagai string tunggal
$#= menyimpan jumlah argumen

Sameer Duwal
sumber
(Ketidaktepatan di atas yang disebutkan oleh @iruvar telah diperbaiki.)
Mateen Ulhaq
13

Penggunaan $@sarana murni dalam kebanyakan kasus "melukai programmer sekeras yang Anda bisa", karena dalam kebanyakan kasus itu mengarah ke masalah dengan pemisahan kata dan dengan spasi dan karakter lain dalam argumen.

Dalam (tebakan) 99% dari semua kasus, diharuskan untuk menyertakannya dalam ": "$@"adalah apa yang dapat digunakan untuk beralih secara andal atas argumen.

for a in "$@"; do something_with "$a"; done
glglgl
sumber
4
Baris Anda dapat ditulis sebagai: untuk a; lakukan something_with "$ a"; selesai ;-)
Alfe
1
@Alfe saya tahu, saya baru saja lupa. Anggap saja for a in start_token "$@" end_token; do something_with "$a"; done:-)
glglgl
9

Dari manual:

@

Perluas ke parameter posisi, mulai dari satu. Ketika ekspansi terjadi dalam tanda kutip ganda, setiap parameter meluas ke kata yang terpisah. Yaitu, "$ @" sama dengan "$ 1" "$ 2" .... Jika ekspansi yang dikutip ganda terjadi dalam suatu kata, ekspansi parameter pertama digabungkan dengan bagian awal dari kata aslinya, dan perluasan dari parameter terakhir digabungkan dengan bagian terakhir dari kata aslinya. Ketika tidak ada parameter posisi, "$ @" dan $ @ perluas apa-apa (mis., Mereka dihapus).

Christoffer Hammarström
sumber
1

Berarti.

Singkatnya, $@memperluas argumen posisi yang diteruskan dari pemanggil ke fungsi atau skrip . Artinya tergantung konteks : Di dalam suatu fungsi, ia memperluas argumen yang diteruskan ke fungsi tersebut. Jika digunakan dalam skrip (tidak di dalam ruang lingkup fungsi), skrip akan diperluas ke argumen yang diteruskan ke skrip tersebut.

$ cat my-sh
#! /bin/sh
echo "$@"

$ ./my-sh "Hi!"
Hi!
$ put () ( echo "$@" )
$ put "Hi!"
Hi!

Pemisahan kata.

Sekarang, topik lain yang sangat penting ketika memahami bagaimana $@berperilaku di shell adalah pemisahan kata . Shell membagi token berdasarkan pada isi IFSvariabel. Nilai standarnya adalah \t\n; yaitu, spasi, tab, dan baris baru.

Memperluas "$@"memberi Anda salinan murni dari argumen yang disahkan. Namun, ekspansi $@tidak selalu. Lebih khusus lagi, jika argumen berisi karakter dari IFS, mereka akan terpecah.


Sebagian besar waktu yang ingin Anda gunakan adalah "$@", bukan $@.

Luis Lavaire
sumber