Bash komut satırı args $ @ vs $ * 'a erişme


327

Birçok SO sorusu ve bash öğreticisinde bash komut dosyalarındaki komut satırı argümanlarına iki şekilde erişebildiğimi görüyorum:

$ ~ >cat testargs.sh 
#!/bin/bash

echo "you passed me" $*
echo "you passed me" $@

Sonuç:

$ ~> bash testargs.sh arg1 arg2
you passed me arg1 arg2
you passed me arg1 arg2

Arasındaki fark nedir $*ve $@?
İlki ne zaman kullanılmalı, ne zaman ikincisi kullanılmalıdır?


bu cevaba bir göz atın: stackoverflow.com/a/842325/671366
kodlama

'daki statik analiz echo "something $@"bir hata gibi davranır
Alex Cohn

Yanıtlar:


437

Fark, özel parametreler alıntılandığında görünür. Farkları açıklayayım:

$ set -- "arg  1" "arg  2" "arg  3"

$ for word in $*; do echo "$word"; done
arg
1
arg
2
arg
3

$ for word in $@; do echo "$word"; done
arg
1
arg
2
arg
3

$ for word in "$*"; do echo "$word"; done
arg  1 arg  2 arg  3

$ for word in "$@"; do echo "$word"; done
arg  1
arg  2
arg  3

alıntı yapmanın önemi üzerine bir örnek daha: "arg" ve sayı arasında 2 boşluk olduğunu unutmayın, ancak $ word alıntı başarısız olursa:

$ for word in "$@"; do echo $word; done
arg 1
arg 2
arg 3

ve bash içinde, "$@"yinelenecek "varsayılan" listedir:

$ for word; do echo "$word"; done
arg  1
arg  2
arg  3

65
+1 Her zaman bu kavramın en iyi bash kılavuzunun tamamen eksik olduğu basit bir örnekle gösterildiğini düşündüm.
chepner

5
Ne zaman $*veya "$*"gerekebilecek olası bir kullanım durumu var mıdır ve amaca $@veya tarafından ulaşılamıyor "$@"mu?
anishsane

5
Komut dosyası parametrelerinin yeni bir komuta parametre olması gereken "sarmalayıcı" komut dosyası için hangi sürüm daha uygundur?
Segfault

7
@Segfault, bu durumda, her zaman "$@"tırnak işaretleri ile seçin .
glenn jackman

2
Bu cevap faydalı örnekler içerir, ancak arkasındaki mekanizmayı da açıklarsa daha iyi olur. Neden böyle çalışıyor?
Lii

255

Bash Hackers Wiki'den kullanışlı ve kullanışlı bir genel bakış tablosu :

$ * ve $ @ tablosuna karşı

burada cüçüncü satırda ilk karakteri $IFS, iç alan ayırıcı, bir kabuk değişkeni.

Bağımsız değişkenler bir komut dosyası değişkeninde depolanacak ve bağımsız değişkenlerin boşluk içermesi bekleniyorsa "$*", içsel alan ayırıcısı $IFSsekme olarak ayarlanmış bir hile kullanmanızı öneririm .


42
... burada "c", $ IFS'in ilk karakteri
glenn jackman

39
... ve $IFS"Dahili Alan Ayırıcı" anlamına gelir.
Serge Stroobandt

Burada alıntılanan girişi içeren bir örnek bulunmaktadır. Giriş de önemlidir!
Serge Stroobandt

Diyelim ki wrapped komutunun işlevselliğini taklit eden hiçbir şey yapmayan bir wrapper betiği oluşturmak istiyorum. Değişkenleri sarmalayıcı komut dosyasından iç komuta geçirmek için hangi sözdizimini kullanmalıyım?
Marinos An

44

, $ *

Birinden başlayarak konumsal parametrelere genişler. Genişletme çift tırnak içinde gerçekleştiğinde, her parametrenin değeri IFS özel değişkeninin ilk karakteriyle ayrılmış tek bir kelimeye genişler. Yani, "$ *", "$ 1c $ 2c ..." ile eşdeğerdir; burada c, IFS değişkeninin değerinin ilk karakteridir. IFS ayarlanmamışsa, parametreler boşluklarla ayrılır. IFS boşsa, parametreler araya giren ayırıcılar olmadan birleştirilir.

$ @

Birinden başlayarak konumsal parametrelere genişler. Genişletme çift tırnak içinde gerçekleştiğinde, her parametre ayrı bir kelimeye genişler. Yani, "$ @", "$ 1" "$ 2" ile eşdeğerdir ... Çift tırnaklı genişleme bir sözcük içinde gerçekleşirse, ilk parametrenin genişlemesi orijinal kelimenin başlangıç ​​bölümü ve genişleme ile birleştirilir. son parametrenin orijinal sözcüğün son kısmı ile birleştirilir. Hiçbir konum parametresi olmadığında, "$ @" ve $ @ hiçbir şeye genişlemez (yani kaldırılır).

Kaynak: Bash man


15

$ @, $ * ile aynıdır, ancak her parametre tırnak içine alınmış bir dizedir, yani parametreler yorumlama veya genişletme olmadan bozulmadan geçirilir. Bu, diğer şeylerin yanı sıra, bağımsız değişken listesindeki her parametrenin ayrı bir kelime olarak görüldüğü anlamına gelir.

Tabii ki, "$ @" belirtilmelidir.

http://tldp.org/LDP/abs/html/internalvariables.html#ARGLIST


1

Bu örnek, onları kullanırken "at" ve "asterix" arasındaki farkı vurgulayabilir. Ben iki dizi "meyve" ve "sebze" ilan

fruits=(apple pear plumm peach melon)            
vegetables=(carrot tomato cucumber potatoe onion)

printf "Fruits:\t%s\n" "${fruits[*]}"            
printf "Fruits:\t%s\n" "${fruits[@]}"            
echo + --------------------------------------------- +      
printf "Vegetables:\t%s\n" "${vegetables[*]}"    
printf "Vegetables:\t%s\n" "${vegetables[@]}"    

Yukarıdaki koda aşağıdaki sonuca bakın:

Fruits: apple pear plumm peach melon
Fruits: apple
Fruits: pear
Fruits: plumm
Fruits: peach
Fruits: melon
+ --------------------------------------------- +
Vegetables: carrot tomato cucumber potatoe onion
Vegetables: carrot
Vegetables: tomato
Vegetables: cucumber
Vegetables: potatoe
Vegetables: onion

6
Bilimsel olarak, domates meyvedir.
Randy

1
Sen haklısın! "Botanikte, bir meyve, çiçek açtıktan sonra yumurtalıktan oluşan çiçekli bitkilerdeki (anjiyospermler olarak da bilinir) tohum taşıyan yapıdır."
Meyve

@Randy: bilimsel olarak konuşursak, tüm meyveler sebzedir ("bitki" ile eşanlamlıdır).
Cris Luengo

@CrisLuengo Instagram Hesabındaki Resim ve Videoları heresy! :)
Randy
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.