“foo () {}” ve “foo () {}” işlevi arasındaki fark


96

Anahtar sözcüğü bashkullanarak veya atlayarak işlevleri tanımlayabilirim function. Fark var mı?

#!/bin/bash

function foo() {
  echo "foo"
}

bar() {
  echo "bar"
}

foo

bar

Her iki işlev de çağrılar foove barbaşarılı ve hiçbir fark göremiyorum. Bu yüzden sadece okunabilirliği arttırmanın mı, yoksa kaçırdığım bir şeyin mi ... olduğunu merak ediyorum.

BTW gibi diğer kabuklarda dash( debian / /bin/shubuntu'da sembolize edilir dash) functionanahtar kelimeyi kullanırken başarısız olur .


8
Ayrıca birlikte veya parantez olmadan: function baz { echo "baz"; }. GreyCat'in wiki'sinde Bashism'i görün .
Manatwork

Yanıtlar:


42

İkinci versiyonun daha taşınabilir olması dışında AFAIK'ta fark yoktur.


32
Bu BÜYÜK bir fark, taşınabilirlik ... Ben sadece (eski) üretim sistemlerinde ÇALIŞMAYAN çok fazla cevap görüyorum ve aynı zamanda sadece Linux üzerinde çalışan seçeneklerle de çok fazla cevap görüyorum. En azından, bunun en taşınabilir yol olmadığı konusunda uyarın ... Düpedüz tehlikeli olabilir (birinden tar cf - /some/thing | ssh user@desthost "cd destinationdir && tar xf - " onları imha etmek için uyarlama yapmadan uyarmasını isteyin) bazı durumlarda felaketler ...). Örneğin: eğer a kullanıyorsanız function tar { #a safe tar with safety checks ... }ve shyok
sayarsa

1
@OlivierDulac sh, functionanahtar kelimeyi tanıyan - ve genel olarak, genel ve standart olmayan özellikleri öne süren kshve bashsunduğunu varsayan komut dosyalarının - eski sürümler üzerinde çalışsalar bile - genellikle yeni üretim sistemlerinde çalışmayacaklarını da eklerim . aynı işletim sistemi. bashhala shbirçok GNU / Linux sistemi sunmaktadır, ancak bazı popüler dağıtımlar performansı artırmak shiçin dash(Debian Almquist Kabuğu) bağlantısına sahip olmaya yönelmiştir. Buna Debian ve Ubuntu da dahildir .
Eliah Kagan

2
Bunun ne kadar "daha taşınabilir" olduğunu tam olarak açıklamadan cevap verilmez.
ivan_pozdeev

Taşınabilirlik, günümüzde endüstrinin tüm ortamların>% 99.9'unda bash veya eşdeğer bir kabuk kullandığı bir tartışma değildir. Okunabilirliği arttırıyor ve iki taraf var: bazı insanlar "işlev" in açık olduğunu söylüyor, posiks standartlarından ya da diğer kabuklardan öğrenen insanlar diş tellerinin daha belirgin bir stil olduğunu söylüyor. Sonunda, grubunuzdan veya şirketinizden birini seçin ve buna bağlı kalın.
Hubert Grzeskowiak

92

functionAnahtar kelime kullanılmaya başlandı ksh . Geleneksel Bourne kabuğu yalnızca foo ()sözdizimine sahipti ve POSIX yalnızca foo ()sözdizimini standartlaştırıyor .

ATT ksh'da (ancak pdksh'de), functionBourne / POSIX sözdiziminde tanımlanan ve fonksiyonlarla tanımlanan fonksiyonlar arasında birkaç fark vardır . Anahtar sözcük tarafından tanımlanan fonksiyonlarda function, typesetyerel bir değişken bildirilir: işlev sona erdiğinde, değişkenin değeri, işleve girmeden önceki değerine sıfırlanır. Klasik sözdizimi ile, kullansanız typesetda kullanmasanız da değişkenlerin global bir kapsamı vardır .

$ ksh -c 'a=global; f () { typeset a=local; }; f; echo $a'
local
$ ksh -c 'a=global; function f { typeset a=local; }; f; echo $a'
global

Ksh'daki bir başka fark, functionanahtar kelimeyle tanımlanan fonksiyonların kendi tuzak içeriğine sahip olmalarıdır. İşlev dışında tanımlanan tuzaklar işlev yürütülürken yoksayılır ve işlev içindeki önemli hatalar tüm işlevden değil işlevden çıkar. Ayrıca, $0tarafından tanımlanan bir işlev işlev adıdır functionile tanımlanan bir işlev ama senaryo ismi ().

Pdksh ATT ksh'ye benzemiyor. Pdksh'de, typesetfonksiyondan bağımsız olarak yerel kapsamda değişkenler yaratır ve yerel tuzaklar yoktur (bununla birlikte kullanım functionbazı küçük farklılıklar yapar - detaylar için man sayfasına bakınız).

Bash ve zsh, functionanahtar kelimeyi ksh ile uyumluluk için tanıtmıştır . Ancak bu kabukları function foo { … }ve foo () { … }kesinlikle bash ve zsh uzantısı olduğu gibi aynıdır function foo () { … }. typesetAnahtar kelime daima (hariç yerel değişkenleri bildirir -gelbette) ve tuzaklar (siz ayarlayarak zsh yerel tuzakları alabilirsiniz yerel olmayan local_trapsseçeneği).


8
Bourne kabuğunun sözdizimini eklemeden önce işlev desteğinin Korn kabuğuna eklendiği foo() commandve Bourne sözdiziminin daha sonra uyumluluk için Korn kabuğuna eklendiği belirtilmelidir.
Stéphane Chazelas

2
Anahtar kelimeden sonra function { ... }; f;atlanması doğru mu? ffunction
Ruslan

32
foo() any-command

Bourne benzeri herhangi bir kabuk tarafından desteklenen Bourne sözdizimi bash, ancak yashson sürümleri posh(yalnızca bileşik komutları destekleyen). (Bourne kabuğu ve AT&T uygulamaları bir bileşik komut olmadığı sürece kshdesteklemez ).foo() any-command > redirectionsany-command

foo() any-compound-command

(bileşik örnekleri komutları: { cmd; }, for i do echo "$i"; done, (cmd)... en yaygın olarak kullanılan { ...; })

Bourne benzeri herhangi bir kabuk ve genel olarak kullanmak istedikleriniz tarafından desteklenen POSIX sözdizimidir.

function foo { ...; }

Bourne sözdiziminden önce gelen Korn kabuğu sözdizimidir. Bunu sadece Korn kabuğunun AT&T uygulaması için yazıyorsanız ve orada aldığı spesifik tedaviye ihtiyaç duyuyorsanız kullanın. Bu sözdizimi POSIX değil, tarafından desteklenen bash, yashve zshKorn kabuk uyumluluk için bu kabuklar (ve olsa pdkshKorn kabuğunun tabanlı varyantları) ona standart sözdizimi herhangi bir farklı tedavi etmiyoruz.

function foo () { ...; }

sözdizimi bir kabuk ve kullanılmamalıdır . Sadece tarafından kazara desteklenecek olur bash, yash, zshve pdkshKorn kabuk tabanlı varyantları. Bu arada, aynı zamanda awkfonksiyon sözdizimi.

Ezoterik listesine girmeye devam edersek,

function foo() other-compound-command

(gibi function foo() (subshell)ya da function foo() for i do; ... done) daha da kötüdür. Bu tarafından desteklenmektedir bash, yashve zshfakat, hatta ksh değil pdkshtabanlı varyantları.

Süre:

function foo() simple command

sadece tarafından desteklenir zsh.


1
Hem functionanahtar kelimeyi hem de parantezleri içeren sözdizimi Bash dilinde belgelenmiştir. Bash 4.2 ve sonraki sürümlerin el kitabı, işlevlerin sözdizimi name () compound-command [ redirections ]veya tarafından bildirildiğini söylüyor function name [()] compound-command [ redirections ]. Bash 4.1.11'de en azından 3.0-beta'a kadar olan, yalnızca anahtar kelimeyi [ function ] name () compound-command [redirection]içeren, functionancak parantezleri içermeyen, ancak hem functionanahtar kelimeyi hem de parantezleri içeren sözdizimini kapsayan tek satırlık olan beta .
nisetama,

@nise, nokta olmasıdır bashtanır function foo {ek olarak foo() {Korn kabuk ile uyumluluk için (ve her zaman vardır) bu yüzden Korn kabuk için yazılmış komut dosyalarını yorumlayabilir. Aynı zamanda destekliyor function foo () {, ancak bunu kullanmak için iyi bir neden yok.
Stéphane Chazelas

2
@ StéphaneChazelas Eh, kullanmak için iyi bir neden olduğunu söyleyebilirim function f() {. Yani, okunabilirlik açısından, İngilizce bilen herkes ve C'yi bilen herkes tarafından, bu setlerden yalnızca biri olarak bir işlev olarak tanınacaktır.
DepressedDaniel

2
Kabul edilen cevap olmalı. Gerçekten önemliYou should never combine the keyword function with the parentheses () when defining a function.
4wk_

Linux / unix otomasyon betikleri için yalnızca bir endüstriden bağımsız standart olan 2019’a hoş geldiniz; hemen hemen her yere kurulmuş bir tercüman (egzotik ortamlar bir yana): bash. Kodunuzu tüm bash özellikleri ile yazın, shebang'ı kullanın ve iyi olacaksınız. Uyumluluk argümanı geçersizdir.
Hubert Grzeskowiak

22

Anlamsal olarak, bu iki form Bash'de eşdeğerdir.

Man sayfasından:

Shell işlevleri aşağıdaki şekilde bildirilmiştir:

name () compound-command [redirection]
function name [()] compound-command [redirection]

Bu adlı bir işlevi tanımlar name. Ayrılmış sözcük işlevi isteğe bağlıdır. Ayrılmış işlev verilirse, parantez isteğe bağlıdır.

EDIT: Ben sadece bu sorunun etiketlendiğini fark ettim posix. POSIX'deki sh, function(o ayrılmıştır rağmen) anahtar kullanılmaz.


3

Bazıları şimdiye kadar doğru cevap verdi, ancak işte özlü özetim:

İkinci versiyon taşınabilirdir ve birçok standart (özellikle POSIX) kabukları ile çalışması muhtemeldir.

İlk versiyon sadece bash ile çalışacaktır, ancak fonksiyon ismini takip eden parantezleri atlayabilirsiniz.

Aksi takdirde, bash onları yorumladıktan sonra aynı varlıkları temsil eder.


Aslında, ilk sürüm bazı kabukları için kabul edilebilir sözdizimi olarak sınırlamak dışında hiçbir anlam ifade etmiyor . Eklemek zaman () vefunction yaptığının sanki kelime kabuk davranır foo(){ ...; }yine de geçersiz sözdizimi olduğu bir kabuk için, tabii ki, hariç. ve böylece yapmalı function foo { ...; }ya da foo(){ ...; }başka türlü yapmalısınız .
mikeserv
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.