“function foo () {}”와“foo () {}”의 차이점


96

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

#!/bin/bash

function foo() {
  echo "foo"
}

bar() {
  echo "bar"
}

foo

bar

함수 호출 foobar성공 모두 차이가 없습니다. 따라서 가독성을 향상시키는 것이지 또는 누락 된 것이 있는지 궁금합니다 ...

dash( debian / ubuntu에서 /bin/shsymlinked) 와 같은 다른 쉘의 BTW dashfunction키워드를 사용할 때 실패 합니다.


8
또한 괄호의 유무에 관계없이 : function baz { echo "baz"; }. GreyCat의 Wiki의 Bashism 을 참조하십시오 .
manatwork

답변:


42

AFAIK는 두 번째 버전이 더 이식 가능하다는 점 외에는 차이가 없습니다.


32
그것은 큰 차이점, 이식성입니다 ... 나는 (구형) 프로덕션 시스템에서는 작동하지 않는 답변이 너무 많고 Linux에서만 작동하는 옵션도 많이 있습니다. 적어도 이것이 가장 휴대 tar cf - /some/thing | ssh user@desthost "cd destinationdir && tar xf - " 하기 쉬운 방법은 아니라고 경고하십시오. 그것은 매우 위험 할 수 있습니다. 누군가에게 desthost의 tar 버전이 "/"를 제거 할 수 있는지 먼저 두 번 확인하도록 경고하지 말라고 요청 하면 어떤 경우에는 재난 ...). 예를 들어 : a를 사용 function tar { #a safe tar with safety checks ... }하고 sh무시하면 ...
Olivier Dulac

1
@OlivierDulac 필자는 키워드를 sh인식 한다고 가정하는 스크립트 ( function일반적으로 쉘이 좋아 ksh하고 bash제공 하는 일반적이지만 비표준 기능을 가정) 는 이전 릴리스에서 작업하더라도 최신 프로덕션 시스템에서는 작동하지 않는 경우가 많다고 덧붙였습니다. 같은 OS. bash여전히 sh많은 GNU / Linux 시스템을 제공하지만 일부 인기있는 배포판은 성능을 향상시키기 위해 (데비안 Almquist SHell)에 sh대한 심볼릭 링크로 전환했습니다 dash. 여기에는 데비안우분투가 포함됩니다 .
Eliah Kagan

2
"더 휴대하기 쉬운"방법을 정교하게 설명하지 않으면 그 대답은 유용하지 않습니다.
ivan_pozdeev

오늘날 업계에서 모든 환경의 99.9 % 이상에서 bash 또는 이와 동등한 쉘을 사용하는 이식성은 논쟁의 여지가 없습니다. 가독성으로 귀결되고 두 가지 측면이 있습니다. 어떤 사람들은 "기능"이 그것을 명확하게하고 posix 표준이나 다른 껍질에서 그것을 배운 사람들은 중괄호가 더 분명한 스타일이라고 말할 것입니다. 결국, 그룹이나 회사 내에서 하나를 선택하고 고수하십시오.
Hubert Grzeskowiak

92

function키워드에 도입 된 KSH . 전통적인 Bourne 쉘foo ()구문 만 가지고 있었고 POSIXfoo ()구문 만 표준화했습니다 .

ATT ksh (pdksh는 아님)에서는 functionBourne / 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와의 호환성을 위해 키워드를 도입했습니다 . 그러나 이러한 껍질에 function foo { … }foo () { … }배쉬와 zsh을 확장 한, 엄격하게 동일하다 function foo () { … }. typeset키워드는 항상 (제외 지역 변수를 선언 -g물론), 그리고 트랩 (당신이 설정하여 zsh을 로컬 트랩을 얻을 수있는 로컬이 아닌 local_traps옵션).


8
Bourne 쉘이 구문을 도입 하기 전에 함수 지원이 Korn 쉘에 foo() command추가되었고 나중에 Bourne 구문이 호환성을 위해 Korn 쉘에 추가되었습니다.
Stéphane Chazelas

2
키워드 뒤에 function { ... }; f;생략 f된 것이 맞 function습니까?
Ruslan

32
foo() any-command

어떤 본쉘 같은 있지만 지원 보른 구문 bash, yash그리고 최신 버전 posh(전용 복합 명령을 지원한다). (보른 외판과의 AT & T 구현을 ksh지원하지 foo() any-command > redirections않는 any-command화합물 명령 비록이다).

foo() any-compound-command

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

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

function foo { ...; }

Bourn 구문보다 오래된 Korn 쉘 구문입니다. Korn 쉘의 AT & T 구현을 위해 특별히 작성하고 여기에서받는 특정 처리가 필요한 경우에만이 기능을 사용하십시오. 그 구문은 POSIX 아니라, 지원하는 bash, yashzshKorn 쉘과의 호환성을 위해 그 쉘 (그리고 비록 pdkshKorn 쉘의 기반 변종은) 그것을 표준 구문과 어떤 다른 치료를하지 않습니다.

function foo () { ...; }

쉘 이 없는 구문이므로 사용하면 안됩니다 . 단지에서 사고에 의해 지원 될 일이 bash, yash, zshpdkshKorn 쉘의 기반 변형. 또한 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.


1
function키워드와 괄호를 모두 포함하는 구문 은 Bash에 문서화되어 있습니다. Bash 4.2 이상의 매뉴얼에는 함수가 구문 name () compound-command [ redirections ]또는 로 선언되어 있다고 나와 있습니다 function name [()] compound-command [ redirections ]. Bash 4.1.11에서 3.0-beta 이상까지는 단 한 줄로 키워드 [ function ] name () compound-command [redirection]를 포함 function하지만 괄호 를 포함하지 않는 구문은 포함 하지 않지만 function키워드와 괄호를 모두 포함하는 구문은 포함하지 않습니다 .
nisetama

@nise, 요점은 즉 bash인식 function foo {이외에 foo() {Korn 쉘과의 호환성을 위해 (항상있다) 그래서 Korn 쉘을 위해 작성된 스크립트를 해석 할 수 있습니다. 그것은 또한 지원 function foo () {하지만, 그것을 사용할 좋은 이유는 없습니다.
Stéphane Chazelas

2
@ StéphaneChazelas 글쎄, 나는 사용할만한 이유가 있다고 말할 것이다 function f() {. 즉, 가독성 측면에서 영어를 아는 사람과 C를 아는 사람은 이러한 집합 중 하나에 대해서만 함수로 인식됩니다.
DepressedDaniel

2
허용되는 답변이어야합니다. 정말 중요You should never combine the keyword function with the parentheses () when defining a function.
4wk_

리눅스 / 유닉스 자동화 스크립트를위한 산업 표준이 단 하나 인 2019에 오신 것을 환영합니다. 거의 모든 곳에 설치되는 통역사 (exotic environment) : bash. 모든 bash 기능으로 코드를 작성하고 shebang을 사용하면 괜찮을 것입니다. 호환성의 주장은 무효입니다.
Hubert Grzeskowiak

22

의미 상,이 두 형식은 Bash와 동일합니다.

매뉴얼 페이지에서 :

쉘 함수는 다음과 같이 선언됩니다.

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

이라는 함수를 정의합니다 name. 예약어 기능 은 선택 사항입니다. 는 IF 기능 예약 된 단어가 공급되고, 괄호는 선택 사항입니다.

편집 : 방금이 질문에 태그가 있음을 알았습니다 posix. POSIX sh에서는 function키워드가 사용되지 않습니다 (예약되어 있지만).


3

지금까지 여러 사람들이 올바르게 대답했지만 다음은 간결한 개요입니다.

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

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

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


실제로 첫 번째 버전은 일부 쉘에 허용되는 구문으로 제한하는 것 외에는 의미가 없습니다 . 당신은을 포함 할 때 () function 방금 한 것처럼 키워드는 쉘은 동작 foo(){ ...; }어쨌든 그것은 잘못된 구문되는 쉘 물론, 제외. 그래서 당신은 무엇을해야 function foo { ...; }당신이해야합니다, 또는 경우 foo(){ ...; }그렇지.
mikeserv
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.