$ @ Có nghĩa là gì trong tập lệnh shell?


Câu trả lời:


240

$@tất cả các tham số được truyền cho tập lệnh.

Chẳng hạn, nếu bạn gọi ./someScript.sh foo barthì $@sẽ bằng foo bar.

Nếu bạn làm:

./someScript.sh foo bar

và sau đó someScript.shtham khảo bên trong :

umbrella_corp_options "$@"

điều này sẽ được chuyển đến umbrella_corp_optionsvới từng tham số riêng lẻ được đặt trong dấu ngoặc kép, cho phép lấy tham số có khoảng trống từ người gọi và chuyển chúng vào.


1
$ @ Sẽ chứa gì nếu tôi làm vậy someScript.sh foo bar "boo far"?
trusktr


7
$ @ là đặc biệt nếu được viết bằng dấu ngoặc kép. Sau đó, nó sẽ dẫn đến một danh sách các giá trị được trích dẫn, trong trường hợp của bạn, trusktr, trong ba đối số "foo", "bar" và "boo far".
Alfe

4
Mặc dù nói chung là như vậy, $@ nhưng không nhất thiết phải đến từ các thông số được truyền cho kịch bản ... ví dụ; set a b "x   y"; printf '(%s)' "$@"đầu ra(a)(b)(x   y)
Peter.O

Tôi thích câu trả lời của Alfe hơn vì anh ấy đưa ra sự khác biệt chính giữa $@$*
donleyp

105

$@gần giống như $*, cả hai đều có nghĩa là "tất cả các đối số dòng lệnh". Chúng thường được sử dụng để đơn giản chuyển tất cả các đối số cho một chương trình khác (do đó hình thành một trình bao bọc xung quanh chương trình khác đó).

Sự khác biệt giữa hai cú pháp xuất hiện khi bạn có một đối số có khoảng trắng trong đó (ví dụ) và đặt $@dấu ngoặc kép:

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.

Ví dụ: Gọi điện thoại

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

sẽ cho kết quả:

"$@": 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

2
Chúng không giống nhau và trang này rõ ràng về tác dụng phụ của $ * khi sử dụng IFS, không nhất thiết phải là không gian. (Nếu chúng giống nhau, sẽ không có bất kỳ điểm nào, ngoài khả năng tương thích có lẽ, trong việc cung cấp cả hai.)
jørgensen

6
Không họ không. Và tôi đã nói như vậy hai dòng dưới đây: "Sự khác biệt giữa hai ..." Để có được những câu ngắn và nâng cao khả năng đọc, người đọc phải đọc nhiều hơn một câu trước khi đưa ra phán quyết: - /
Alfe

2
Alfe, Christoffer đã chèn một từ "gần như" đó đã tạo ra một sự khác biệt, mà không phải hy sinh bất kỳ sự căng thẳng hay dễ đọc nào. Trong thực tế, tôi đã đưa ra câu trả lời này (trái ngược với câu trả lời được chấp nhận) chính xác do sự nhấn mạnh tinh tế của sự khác biệt ... - trước khi nhận ra rằng nó gần như trái với ý muốn của bạn! ;)
Sz.

Tôi nghĩ rằng từ đó đã tạo ra một sự khác biệt cho những người đưa ra phán quyết ngay sau khi đọc câu đầu tiên ;-) và nó không bao giờ trái với ý muốn của tôi. Tôi thực sự muốn viết cũng cho những người này.
Alfe

Rất không rõ ràng. wrappedProgram "$*"-> separated by single spaces.nhưng trong ví dụ thứ 2 của bạn, chúng không bị ngăn cách bởi các khoảng trắng.
Felix Dombek

36

Đây là các đối số dòng lệnh trong đó:

$@= lưu trữ tất cả các đối số trong danh sách chuỗi
$*= lưu trữ tất cả các đối số dưới dạng một chuỗi
$#= lưu trữ số lượng đối số


(Sự không chính xác ở trên được đề cập bởi @iruvar đã được sửa chữa.)
Mateen Ulhaq

13

Việc sử dụng nguyên chất $@ phương tiện trong hầu hết các trường hợp "làm tổn thương lập trình viên hết sức có thể", bởi vì trong hầu hết các trường hợp, nó dẫn đến các vấn đề về tách từ và với khoảng trắng và các ký tự khác trong các đối số.

Trong (đoán) 99% của tất cả các trường hợp, cần phải gửi nó vào " : "$@"là những gì có thể được sử dụng để lặp lại một cách đáng tin cậy trên các đối số.

for a in "$@"; do something_with "$a"; done

4
Dòng của bạn có thể được viết là: for a; làm một cái gì đó với "$ a"; xong ;-)
Alfe

1
@ Alfe Tôi biết, tôi chỉ quên nó thôi. Hãy nghĩ về nó như for a in start_token "$@" end_token; do something_with "$a"; done:-)
glglgl

9

Từ hướng dẫn:

@

Mở rộng đến các tham số vị trí, bắt đầu từ một. Khi mở rộng xảy ra trong dấu ngoặc kép, mỗi tham số sẽ mở rộng thành một từ riêng biệt. Nghĩa là, "$ @" tương đương với "$ 1" "$ 2" .... Nếu việc mở rộng trích dẫn kép xảy ra trong một từ, việc mở rộng tham số đầu tiên được nối với phần đầu của từ gốc và mở rộng tham số cuối cùng được nối với phần cuối của từ gốc. Khi không có tham số vị trí, "$ @" và $ @ mở rộng thành không có gì (nghĩa là chúng bị xóa).


1

Ý nghĩa.

Tóm lại, $@mở rộng cho các đối số vị trí được truyền từ người gọi đến một hàm hoặc một tập lệnh . Ý nghĩa của nó là phụ thuộc vào ngữ cảnh : Bên trong một hàm, nó mở rộng tới các đối số được truyền cho hàm đó. Nếu được sử dụng trong một tập lệnh (không nằm trong phạm vi một hàm), nó sẽ mở rộng thành các đối số được truyền cho tập lệnh đó.

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

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

Chia tách từ.

Bây giờ, một chủ đề khác có tầm quan trọng tối cao khi hiểu cách $@hành xử trong vỏ là tách từ . Shell tách mã thông báo dựa trên nội dung của IFSbiến. Giá trị mặc định của nó là \t\n; tức là khoảng trắng, tab và dòng mới.

Mở rộng "$@"cung cấp cho bạn một bản sao nguyên sơ của các đối số được thông qua. Tuy nhiên, việc mở rộng $@sẽ không luôn luôn. Cụ thể hơn, nếu các đối số chứa các ký tự từ IFS, chúng sẽ phân tách.


Hầu hết thời gian những gì bạn sẽ muốn sử dụng là "$@", không $@.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.