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

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

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

#!/bin/bash

function foo() {
  echo "foo"
}

bar() {
  echo "bar"
}

foo

bar

함수에 대한 호출은 모두 foo성공했으며 bar아무런 차이도 볼 수 없습니다. 그래서 이것이 단지 가독성을 위한 것인지 아니면 뭔가 빠진 것인지 궁금합니다.

그런데 다른 쉘(예 : dashdebian/ubuntu의 /bin/sh심볼릭 링크 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 구문으로 정의된 함수와 Bourne/POSIX 구문으로 정의된 함수 간에 몇 가지 차이점이 있습니다. 에서 정의한 함수 내에서 functiontypeset키워드는 지역 변수를 선언합니다. 함수가 종료되면 이 변수의 값은 함수를 시작하기 전의 값으로 재설정됩니다. 클래식 구문을 사용하면 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

내가 알 수 있는 한, 두 번째 버전이 이식성이 더 좋다는 것 외에는 차이점이 없습니다.

답변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. yashzsh, 이러한 쉘(및 pdkshKorn 쉘의 - 기반 변형)은 이를 표준 구문과 다르게 처리하지 않습니다.

function foo () { ...; }

구문은 다음과 같습니다아니요쉘과사용해서는 안 된다. 이는 bash, 및 Korn 쉘 yash의 기본 변형 에서만 우연히 지원됩니다 zsh. pdksh그런데 이것도 awk함수형 구문입니다.

난해한 목록을 계속해서 따라가면,

function foo() other-compound-command

( function foo() (subshell)또는 function foo() for i do; ... done) 더 나쁘다. bash, yash모두 지원 zsh하지만 ksh는 지원하지 않으며 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가 이를 해석한 후 동일한 엔터티를 나타냅니다.

관련 정보