$ @ หมายถึงอะไรในเชลล์สคริปต์


189

เครื่องหมายดอลลาร์ตามด้วยเครื่องหมาย at ( @) หมายถึงอะไรในเชลล์สคริปต์

ตัวอย่างเช่น:

umbrella_corp_options $@


คำตอบ:


242

$@คือพารามิเตอร์ทั้งหมดที่ส่งผ่านไปยังสคริปต์

ตัวอย่างเช่นถ้าคุณเรียก./someScript.sh foo barแล้วจะเท่ากับ$@foo bar

ถ้าคุณทำ:

./someScript.sh foo bar

แล้วภายในsomeScript.shการอ้างอิง:

umbrella_corp_options "$@"

สิ่งนี้จะถูกส่งผ่านไปumbrella_corp_optionsพร้อมกับพารามิเตอร์แต่ละตัวที่อยู่ในเครื่องหมายคำพูดคู่อนุญาตให้ใช้พารามิเตอร์ที่มีช่องว่างจากผู้เรียกและส่งต่อไป


1
สิ่งที่จะ $ @ ประกอบด้วยถ้าฉันไม่someScript.sh foo bar "boo far"?
trusktr


7
$ @ พิเศษถ้าเขียนด้วยเครื่องหมายคำพูดคู่ จากนั้นจะส่งผลให้รายการค่าที่ยกมาในกรณีของคุณ trusktr ในสามข้อโต้แย้ง "foo", "bar" และ "boo far"
Alfe

4
แม้ว่ามันจะเป็นโดยทั่วไปกรณีที่$@ไม่ไม่จำเป็นต้องมาจาก PARAMATERS ส่งผ่านไปยังสคริปต์ ... เช่น; set a b "x   y"; printf '(%s)' "$@"เอาท์พุท(a)(b)(x   y)
Peter.O

ฉันชอบคำตอบของ Alfe ดีกว่าเพราะเขาให้ความแตกต่างที่สำคัญระหว่าง$@และ$*
donleyp

106

$@เกือบเหมือนกัน$*ทั้งความหมาย "อาร์กิวเมนต์บรรทัดคำสั่งทั้งหมด" พวกเขามักจะใช้เพียงแค่ส่งข้อโต้แย้งทั้งหมดไปยังโปรแกรมอื่น (ดังนั้นการสร้างเสื้อคลุมรอบโปรแกรมอื่น ๆ

ความแตกต่างระหว่างไวยากรณ์ทั้งสองจะปรากฏขึ้นเมื่อคุณมีอาร์กิวเมนต์ที่มีช่องว่างในนั้น (เช่น) และใส่$@เครื่องหมายคำพูดคู่:

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.

ตัวอย่าง: การโทร

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

จะส่งผลให้:

"$@": 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
พวกเขาจะไม่เหมือนกันและ manpage ชัดเจนเกี่ยวกับผลข้างเคียงของ $ * โดยใช้ IFS ซึ่งไม่จำเป็นต้องเว้นวรรค (หากพวกเขาเหมือนกันจะไม่มีจุดใด ๆ นอกเหนือจากการทำงานร่วมกันบางทีในการให้บริการทั้งสอง.)
Jorgensen

6
ไม่พวกเขาไม่ได้เป็น. และฉันบอกว่าสองบรรทัดด้านล่าง: "ความแตกต่างระหว่างสอง ... " เพื่อให้ได้ประโยคสั้น ๆ และเพิ่มความสามารถในการอ่านผู้อ่านต้องอ่านมากกว่าหนึ่งประโยคก่อนที่จะตัดสิน: - /
Alfe

2
Alfe การที่ Christoffer แทรกคำหนึ่งคำว่า "เกือบ" ทำให้เกิดความแตกต่างโดยไม่ต้องเสียสละหรืออ่านง่าย ในความเป็นจริงฉัน upvoted คำตอบนี้ (ตรงข้ามกับคำตอบที่ยอมรับ) เนื่องจากการเน้นความแตกต่างที่ลึกซึ้ง... - ก่อนที่จะตระหนักว่ามันเกือบจะขัดกับความประสงค์ของคุณ! ;)
Sz.

ฉันคิดว่าคำนี้สร้างความแตกต่างให้กับผู้ที่ตัดสินคดีหลังจากอ่านประโยคแรก ;-) และมันไม่เคยขัดกับความประสงค์ของฉัน ฉันอยากจะเขียนสำหรับคนเหล่านี้ด้วย
Alfe

ไม่ชัดเจนมาก wrappedProgram "$*"-> separated by single spaces.แต่ในตัวอย่างที่ 2 ของคุณจะไม่ถูกคั่นด้วยช่องว่างเดียว
เฟลิกซ์ Dombek

36

นี่คืออาร์กิวเมนต์บรรทัดคำสั่งที่:

$@= เก็บอาร์กิวเมนต์ทั้งหมดในรายการสตริง
$*= เก็บอาร์กิวเมนต์ทั้งหมดเป็นสตริงเดี่ยว
$#= เก็บจำนวนอาร์กิวเมนต์


(ความไม่ถูกต้องที่กล่าวถึงข้างต้นโดย @iruvar ได้รับการแก้ไขแล้ว)
Mateen Ulhaq

13

การใช้วิธีการที่บริสุทธิ์$@ในกรณีส่วนใหญ่ "ทำให้โปรแกรมเมอร์ยากที่สุดเท่าที่จะทำได้" เพราะในกรณีส่วนใหญ่มันนำไปสู่ปัญหาการแยกคำและช่องว่างและอักขระอื่น ๆ ในการโต้แย้ง

ใน (เดา) 99% ของทุกกรณีจำเป็นต้องใส่ไว้ใน": "$@"เป็นสิ่งที่สามารถใช้ในการทำซ้ำข้อโต้แย้งได้อย่างน่าเชื่อถือ

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

4
บรรทัดของคุณสามารถเขียนเป็น: สำหรับ; ทำบางสิ่งด้วย "$ a"; เสร็จแล้ว ;-)
Alfe

1
@ รู้ฉันรู้ฉันเพิ่งลืมมัน คิดว่ามันเป็นfor a in start_token "$@" end_token; do something_with "$a"; done:-)
glglgl

9

จากคู่มือ:

แอท

ขยายไปยังพารามิเตอร์ตำแหน่งโดยเริ่มจากหนึ่งพารามิเตอร์ เมื่อการขยายเกิดขึ้นภายในเครื่องหมายคำพูดคู่พารามิเตอร์แต่ละตัวจะขยายเป็นคำแยกต่างหาก นั่นคือ "$ @" เทียบเท่ากับ "$ 1" "$ 2" .... หากการขยายตัวที่มีเครื่องหมายคำพูดเกิดขึ้นภายในคำการขยายตัวของพารามิเตอร์ตัวแรกจะรวมกับส่วนเริ่มต้นของคำเดิมและ การขยายตัวของพารามิเตอร์สุดท้ายจะเข้าร่วมกับส่วนสุดท้ายของคำเดิม เมื่อไม่มีพารามิเตอร์ตำแหน่ง "$ @" และ $ @ จะขยายเป็นไม่มีอะไร (เช่นจะถูกลบออก)


1

ความหมาย

ในช่วงสั้น ๆขยายไปยังข้อโต้แย้งตำแหน่งผ่านจากโทรไปทั้งฟังก์ชั่นหรือสคริปต์$@ ความหมายของมันขึ้นอยู่กับบริบท : ภายในฟังก์ชั่นมันจะขยายไปยังอาร์กิวเมนต์ที่ส่งผ่านไปยังฟังก์ชันดังกล่าว หากใช้ในสคริปต์ (ไม่ใช่ภายในขอบเขตของฟังก์ชัน) มันจะขยายไปยังอาร์กิวเมนต์ที่ส่งผ่านไปยังสคริปต์ดังกล่าว

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

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

การแยกคำ

ตอนนี้หัวข้ออื่นที่มีความสำคัญยิ่งเมื่อความเข้าใจวิธีการ$@ทำงานในเปลือกเป็นแยกคำ เชลล์แยกโทเค็นตามเนื้อหาของIFSตัวแปร ค่าเริ่มต้นคือ\t\n; เช่นช่องว่างแท็บและขึ้นบรรทัดใหม่

การขยาย"$@"จะให้สำเนาของอาร์กิวเมนต์ที่ผ่านไป อย่างไรก็ตามการขยายตัว$@จะไม่เสมอไป โดยเฉพาะอย่างยิ่งหากข้อโต้แย้งมีตัวละครจากIFSพวกเขาจะแยก


เวลาส่วนใหญ่ของสิ่งที่คุณจะต้องการที่จะใช้งานไม่ได้"$@"$@

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.