Shell işlev tanımında parantez `()` nedir?


20

Bir fonksiyon şöyle tanımlanır:

do_something () {
    do it
}

'Do_something' adını ve hareket kodunu içine almak için kullanılan parantezin adını anlayabiliyordum, ancak ()Bash betiklerinde adlandırılmış parametreler olmadığı için buradaki amacı ne olduğu hakkında bir fikir edemiyorum . Olarak tanımlamak daha iyi ve anlaşılır olabilir.

do_something {
  do it
}

Bu, mevcut sözdizimi ile çakışmaz ve hatta daha fazla adlandırılmış parametre olmadığını beyan eder. ()Burada kullanımı nedir ?


Yanıtlar:


44

Bu olmadan, ()sözdizimi gerçekten belirsiz olurdu.

Bir işlevi tanımlamak için bazı belirgin sözdizimleri olmalı ve diğer kabuk sözdizimini büyük ölçüde değiştirmeden , bu olamaz:

do_something {
    # one or more commands go here
}

Bunun "şu anki sözdizimiyle çakışmadığını" söylediniz ama öyle! İlk satırını çalıştırmaya çalıştığınızda herhangi bir sözdizimi hatası almadığınızı fark edin . Bir hata alıyorsunuz, ancak sözdizimi ile ilgili bir hata değil. İkincisi, ile }, bir sözdizimi hatası, ancak ilk satır değil. Bunun yerine, do_something {denilen bir komutu çalıştırmayı dener do_somethingve {bu komutu bir argüman olarak iletir:

$ do_something {
do_something: command not found

Zaten adı verilen bir komut do_somethingvarsa, onu çalıştırıyorsunuzdur. Zaten adında bir fonksiyon varsa do_something, bunu aradığınız . Genel olarak sözdiziminin belirsiz olması önemlidir, ancak özellikle bir işlevi yanlışlıkla çağırmadan yeniden tanımlamanın mümkün olması da önemlidir. Bir fonksiyon tanımlamak ve onu çağırmak aynı görünmemelidir.

Kabuk nasıl davranır {ve (.

Gibi type {size söyleyecektir, {bir kabuk anahtar kelimedir. Bu gibi yapar [[. Aksi halde bir komut olacağı bir durumda kullanılırsa {, özel anlambilim taşır. Özellikle, komut gruplandırması gerçekleştirir. Bununla birlikte, diğer durumlarda, değişmez bir {karakteri göstermek için çıkmadan kullanılabilir . Buna, komutun ikinci veya daha sonraki bir sözcüğü olarak geçilmesi durumu da dahildir.

Tabii ki, Bash şu anda olduğundan daha farklı davranmak için dizayn edilmiş olabilir{ . Bununla birlikte, sözdizimi artık POSIX kabuğu ile uyumlu olmayacaktı ve Bash, gerçekten bir Bourne tarzı kabuk olmayacaktı ve birçok kabuk komut dosyası çalıştıramayacaktı.

Buna karşılık, (bir kabuk meta karakterdir. Her zaman bir komuta görünür ve alıntı değilse özel olarak ele (ile olan ' ', " "ya da \). Bu nedenle sözdiziminde belirsizlik yoktur:

do_something() {
    # one or more commands go here
}

Bu başka bir şey ifade edemezdi. Bash'in fonksiyonları olmasaydı, sözdizimi hatası olurdu, aynı sebeple echo foo(bar)sözdizimi hatası.

Eğer ()gösterimden gerçekten hoşlanmıyorsanız, o zaman anahtar kelimeyi kullanabilir functionve sudodus'un söylediği gibi atlayabilirsiniz . Bunun, diğer Bourne tarzı mermilerin çoğunda işlevleri tanımlamak için sözdiziminin bir parçası olmadığını ve bazılarında desteklendiğini, ancak bu şekilde tanımlanmış işlevlerin farklı semantiklere sahip olduğunu ve bu nedenle onu kullanan bir komut dosyasının taşınabilir olmayacağını unutmayın. (Bu sözdiziminin net olmama nedeni function, Bash'in kendisinin, izleyenlerin bir işlev tanımının başlangıcı olduğunu gösteren bir anahtar kelime olmasıdır.)

Son olarak, çoğu fonksiyon tanımının {pratikte kullanılmasına rağmen, herhangi bir bileşik komutuna izin verildiğini unutmayın. Vücudu her zaman bir deniz kabuğu altında çalıştırmak istediğiniz bir işleve sahipseniz, ( )yerine kullanabilirsiniz { }.


1
Daha yüksek düzeyde, bu insan beklentileri ve okunabilirlik ile ilgilidir. Çoğu dilde, özellikle C, fortran ve bash betik dillerinin geliştirildiği süre boyunca yaygın olan diğerleri, bir işlev / alt yordam her zaman parantez içine alınmış, muhtemelen boş olan bir tartışma listesine sahiptir. Bu paradigmayı değiştir ve dili anlamayı zorlaştırıyorsun.
jamesqf

15

()Jetonu Eğer bir işlev ilan olduğunu kabuk tercüman söylemektir.

$ do_something () { echo 'do it'; } ; do_something
do it

Alternatif olarak bashbirfunction

function do_something {
 echo 'do it'
}

veya tek bir astar olarak test edebilirsiniz.

$ bash -c "function do_something { echo 'do it'; } ; do_something"
do it

2
functionAnahtar ön-POSIX Ksh-izm olduğu için geriye dönük uyumluluk Bash destekler; ancak, bash bunu çok kötü bir şekilde desteklemektedir (eski ksh'ın bu biçimde bildirilen işlevlerde yaptığı gibi değişkenleri işlev-yerel varsayılan yapmamak). Sonuç olarak, yeni kod için ideal değildir. Bkz. Wiki.bash-hackers.org/scripting/obsolete
Charles Duffy

@CharlesDuffy, Bu açıklama için teşekkürler :-)
sudodus

1
@CharlesDuffy Ksh ve bash'ın ksh değişkeninde yerel, bash'da global değişken yapan bazı sözdizimini kabul ettiğini mi söylüyorsunuz? Bu doğru gelmiyor. Kısmen bağlı My anlayış, söz konusu yayının ve kontrol (ksh93 olarak), bu Ksh olduğu değişkenleri yerel yapar az , bash daha durumlara asla daha. Bash, bir işlevi typesetolmadan -gher zaman bir yerel değişken bildirir. İle functionanahtar kelime, bash ve Ksh kapsam değişkenleri aynı şekilde , onlar değil mi?
Eliah Kagan

Charles gösterilmiştir atıfta olmuştur ne düşünüyorsunuz @EliahKagan Gille cevabı burada
Sergiy Kolodyazhnyy

9

Ne kadar çok gerçek-brace tarzı sen?

Diğer, mükemmel parantez stilleri düşünün:

foo
{
  ...
}
foo
  {
    ...
  }
foo
  while ...; do ...; done # Look, ma! No braces!
foo
( ... ) # Look, ma! No braces and a subshell to boot!

Kabuk bunların fonksiyon tanımları olduğunu ve sadece fookomut listeleri tarafından takip edilen bir komut olmadığını nasıl söyleyebilir ? Tüm bu durumlarda, anahtar kelime ()veya benzeri ek bir belirsizleştirme faktörü functiongerekir.


İkinci düşüncede, aslında OTBS değil, çünkü OTBS'in yeni bir hatta diş tellerine izin verdiği yer işlev tanımları içindir.
muru

3
Bence onu OTBS olarak nitelendirmek konusunda haklı olduğuna dair bir argüman var, çünkü C ve C ++ 'daki fonksiyonların aksine, Bourne tarzı bir kabuk betiğindeki bir fonksiyon tanımı doğrudan başka bir fonksiyon tanımının gövdesine yerleştirilebilir ve tartışılabilir ayırt edilmeyi hak etmiyor. (Ya da belki bu, Java programlamada popüler olan ve yöntemlerin OTBS yerine aynı satırda aynı hizada olduğu stildir.) Her iki durumda da, sözdiziminin çalışması için küme yerleşimi üzerine sıkı kısıtlamalar getirmesi konusunda mükemmel bir noktaya değinirsiniz. hiç ()ya da onun gibi bir şey.
Eliah Kagan
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.