"function foo() {}"와 "foo() {}"의 차이점

"function foo() {}"와 "foo() {}"의 차이점

bash키워드를 사용하거나 생략하여 함수를 정의할 수 있습니다 function. 차이점이 있나요?

#!/bin/bash

function foo() {
  echo "foo"
}

bar() {
  echo "bar"
}

foo

bar

함수 호출 foobar성공이 모두 이루어졌는데 아무런 차이가 없습니다. 그래서 가독성을 높이기 위한 것인지, 아니면 제가 놓치고 있는 부분이 있는지 궁금합니다...

dash( 데비안/우분투에서 /bin/sh심볼릭 링크됨 ) 과 같은 다른 쉘의 BTW는 키워드를 dash사용할 때 실패합니다 function.

답변1

두 가지 다른 구문이 있는 이유는 역사적입니다. 키워드 function는 다음에서 나왔습니다.크쉬. C ()에서 영감을 받은 구문은본 쉘.POSIXBourne foo ()구문만 표준화합니다. Bash와 zsh는 하이브리드뿐만 아니라 둘 다 지원합니다 function foo () { … }. ATT ksh를 제외하고 결과 함수는 정확히 동일합니다.

구문에 주의하세요 (). 함수 이름은 별칭 확장의 영향을 받습니다.

alias f=g
f () { echo foo; }
type f               # f is an alias for g
type g               # g is a shell function
f                    # alias f → function g → print foo
\f                   # no alias lookup → f: not found
g                    # function g

functionATT ksh(pdksh 및 mksh와 같은 하위 항목 제외)에서는 Bourne/POSIX 구문으로 정의된 함수와 에서 정의한 함수 간에 몇 가지 차이점이 있습니다 . 로 정의된 함수에서 function키워드 typeset는 지역 변수를 선언합니다. 함수가 종료되면 변수 값은 함수를 시작하기 전의 값으로 재설정됩니다. 클래식 구문을 사용하면 변수는 사용 typeset여부에 관계없이 전역 범위를 갖습니다.

$ 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의 또 다른 차이점은 키워드로 정의된 함수에 function자체 트랩 컨텍스트가 있다는 것입니다. 함수 외부에 정의된 트랩은 함수 실행 중에 무시되며, 함수 내부의 치명적인 오류는 전체 스크립트가 아닌 함수에서만 종료됩니다. 또한 는 $0로 정의된 함수의 함수 이름이지만 function로 정의된 함수의 스크립트 이름입니다 ().

Pdksh는 ATT ksh를 에뮬레이트하지 않습니다. pdksh에서는 typeset함수에 관계없이 로컬 범위의 변수를 생성하며 로컬 트랩이 없습니다(사용하면 function약간의 차이가 있지만 자세한 내용은 매뉴얼 페이지를 참조하세요).

Bash와 zsh는 functionksh와의 호환성을 위한 키워드를 도입했습니다. 그러나 이러한 셸에서는 bash 및 zsh 확장과 마찬가지로 엄격하게 동일합니다 function foo { … }( 위에 설명된 대로 정의를 구문 분석할 때 잠재적인 별칭 확장 제외). 키워드 는 항상 로컬 변수를 선언하며(물론 제외 ) 트랩은 로컬이 아닙니다(옵션을 설정하여 zsh에서 로컬 트랩을 얻을 수 있습니다 ).foo () { … }function foo () { … }typeset-glocal_traps

답변2

두 번째 버전이 더 이식성이 있다는 점을 제외하면 AFAIK에는 차이가 없습니다.

답변3

foo() any-command

Bourne과 유사한 쉘에서 지원되는 Bourne 구문이지만 bash,yash및 최신 버전 posh(복합 명령만 지원). (Bourne 쉘 및 AT&T 구현은 복합 명령이 아닌 한 지원 ksh하지 않습니다 ).foo() any-command > redirectionsany-command

foo() any-compound-command

(복합 명령의 예: { cmd; }, for i do echo "$i"; done, (cmd)... 가장 일반적으로 사용되는 것은 { ...; })

Bourne과 유사한 쉘에서 지원하는 POSIX 구문이며 일반적으로 사용하려는 구문입니다.

function foo { ...; }

Bourne 구문보다 앞서는 Korn 쉘 구문입니다. Korn 셸의 AT&T 구현을 위해 특별히 작성하고 거기서 받는 특정 처리가 필요한 경우에만 이 항목을 사용하십시오. 해당 구문은 POSIX는 아니지만 에서 지원되며 Korn bash셸 과의 호환성을 위해 해당 셸(및 Korn 셸의 기반 변형)은 표준 구문과 다르게 처리하지 않습니다.yashzshpdksh

function foo () { ...; }

의 구문입니다아니요껍질과사용해서는 안 된다. Korn 셸의 , 및 기반 변형 bash에서만 우연히 yash지원 됩니다 . 덧붙여서, 함수 구문이기도 합니다 .zshpdkshawk

난해한 목록을 계속해서 내려가면,

function foo() other-compound-command

(좋아요 function foo() (subshell)또는 function foo() for i do; ... done)은 더 나쁩니다. bash, yash및 에서는 지원되지만 zshksh는 지원되지 않으며 pdksh기반 변형도 지원됩니다.

하는 동안:

function foo() simple command

에서만 지원됩니다 zsh.

foo bar() any-command

또는:

$function_list() any-command

한 번에 여러 함수를 정의하는 것은 다음에서만 지원됩니다.zsh

function { body; } args
() any-compound-command args

어느 것이익명 함수호출은 에서만 지원됩니다 zsh.

답변4

지금까지 몇몇 다른 사람들이 올바르게 답변했지만 여기에 간략한 개요가 있습니다.

두 번째 버전은 이식 가능하며 많은 표준(특히 POSIX) 셸에서 작동할 가능성이 높습니다.

첫 번째 버전은 bash에서만 작동하지만 함수 이름 뒤의 괄호를 생략할 수 있습니다.

그렇지 않으면 bash가 해석한 후 동일한 엔터티를 나타냅니다.

관련 정보