쉘 함수 정의에서 괄호`()`를 사용하는 것은 무엇입니까?


20

기능은 다음과 같이 정의됩니다.

do_something () {
    do it
}

액션 코드를 캡슐화하는 이름 'do_something'과 중괄호를 이해할 수 있지만 ()Bash 스크립트에는 명명 된 매개 변수가 없으므로 여기 에서 목적이 무엇인지 알 수 없습니다 . 그것을 다음과 같이 정의하는 것이 더 좋고 간단 할 수 있습니다

do_something {
  do it
}

현재 구문과 충돌하지 않으며 명명 된 매개 변수가 없다고 선언합니다. ()여기서 사용법은 무엇입니까 ?


답변:


44

이 없으면 ()구문이 실제로 모호합니다.

있을하는 일부 기능을 정의하기위한 명백한 구문을 실질적으로 변경하지 않고 다른 쉘 구문,이 수 없습니다

do_something {
    # one or more commands go here
}

당신은 이것이 "현재 구문에 맞지 않는다"고 말했지만 그렇지 않습니다! 첫 줄 을 실행할 때 어떤 종류의 구문 오류도 발생하지 않습니다 . 오류가 발생하지만 구문에 대한 오류는 아닙니다. 이있는 두 번째 줄 }은 구문 오류이지만 첫 번째 줄은 그렇지 않습니다. 대신, do_something {호출 된 명령을 실행하고 해당 명령의 인수로 do_something전달 하려고 시도합니다 {.

$ do_something {
do_something: command not found

이미라는 명령이 있으면 do_something실행 중입니다. 이미라는 함수가 있다면 do_something, 당신은 그것을 요구하고있다 . 일반적으로 구문은 분명해야하지만, 실수로 함수를 호출하지 않고도 함수를 재정의 할 수 있어야합니다. 함수를 정의하고 호출하면 동일하게 보이지 않아야합니다.

쉘이 취급하는 방법 {(.

으로 type {당신을 말할 것이다, {쉘 키워드입니다. 이것은 그것을 좋아 [[합니다. 명령이 아닌 상황에서 사용되는 경우 {특수 의미를 갖습니다. 특히 명령 그룹화를 수행합니다. 그러나 다른 상황에서는 이스케이프 처리되어 리터럴 {문자 를 나타낼 수 있습니다 . 여기에는 명령의 두 번째 또는 후속 단어로 전달하는 상황이 포함됩니다.

물론 Bash { 현재와 ​​다르게 취급하도록 설계되었을 있습니다 . 그러나이 구문은 더 이상 POSIX 셸과 호환되지 않았으며 Bash는 실제로 Bourne 스타일 셸이 아니므로 많은 셸 스크립트를 실행할 수 없습니다.

반대로 (쉘 메타 문자입니다. 그것은 항상 명령에 나타나고 인용되지 않은 경우 특수 처리 (함께 ' ', " "또는 \). 따라서 구문에는 모호성이 없습니다.

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

그것은 다른 것을 의미 할 수 없습니다. Bash에 함수가 없다면 구문 오류 일 것입니다. 같은 이유로 echo foo(bar)구문 오류가 있습니다.

()표기법을 정말로 싫어한다면 sudodus에서 언급했듯이 키워드를 사용 function하고 생략 할 수 있습니다 . 이것은 대부분의 다른 Bourne 스타일 쉘에서 함수를 정의하기위한 구문의 일부 가 아니며 , 일부에서는 지원되지만 다른 방식으로 정의 된 함수는이를 의미 하므로이를 사용하는 스크립트는 이식성이 없습니다. (이 구문이 모호하지 않은 이유 는 그 자체가 Bash의 키워드이기 때문에 뒤에 오는 것이 함수 정의의 시작임을 나타냅니다.)function

마지막으로 대부분의 함수 정의 {는 실제로 사용 되지만 모든 복합 명령이 허용됩니다. 본문이 항상 서브 쉘에서 실행되기를 원하는 함수가있는 경우 ( )보다 사용할 수 있습니다 { }.


1
더 높은 수준에서, 그것은 인간의 기대와 가독성에 관한 것입니다. 대부분의 언어, 특히 C, 포트란 및 기타 언어에서 bash 스크립팅 언어가 개발 될 때 일반적으로 사용되는 함수 / 서브 루틴에는 항상 괄호로 묶인 인수 목록이 비어있을 수 있습니다. 그 패러다임을 바꾸면 언어를 이해하기가 더 어려워집니다.
jamesqf

15

()토큰은 함수를 선언하고 있다는 쉘 인터프리터를 이야기하는 것입니다.

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

대안 bashfunction

function do_something {
 echo 'do it'
}

또는 하나의 라이너로 테스트 할 수 있습니다

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

2
function키워드는 사전 POSIX의 KSH-주의입니다 이전 버전과의 호환성을 위해 bash는 지원; 그러나 bash는 잘못 지원합니다 (이전 양식에서 선언 된 함수에서 오래된 ksh가했던 것처럼 변수를 로컬 함수 기본값으로 설정하지 않음). 결과적으로 새로운 코드에는 적합하지 않습니다. wiki.bash-hackers.org/scripting/obsolete
Charles Duffy를

@CharlesDuffy,이 설명을 주셔서 감사합니다 :-)
sudodus

1
@CharlesDuffy ksh와 bash는 ksh에서 지역 변수를 만들지 만 bash에서는 전역 변수를 만드는 구문을 허용합니까? 소리가 안 들려요. 그 게시물검사 (ksh93에서) 에 부분적으로 기초를 둔 나의 이해 는 ksh가 bash보다 적은 상황 에서 변수를 로컬로 만든다는 것입니다. bash 에서 함수가 typeset없으면 -g항상 지역 변수를 선언합니다. 으로 function키워드, 배쉬 및 KSH 범위 변수 같은 방식으로 , 그들은을하지?
Eliah Kagan

@EliahKagan 찰스가 말한 것이 여기 길의 답변 에서 입증되었다고 생각 합니다
Sergiy Kolodyazhnyy

9

당신의 참-중괄호 스타일-이 얼마나 !

다른 완벽하게 좋은 버팀대 스타일을 고려하십시오.

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

쉘은 단순히 명령 foo뒤에 명령리스트가 아니라 함수 정의라고 어떻게 알 수 있습니까? 이러한 모든 경우에, 추가로 명확하게하는 요인처럼 ()또는 function키워드가 필요합니다.


OTBS가 새 줄에서 중괄호를 허용하는 곳은 함수 정의를위한 것이기 때문에 두 번째로 생각하면 실제로는 OTBS가 아닙니다.
muru

3
C와 C ++의 함수와 달리 Bourne 스타일 쉘 스크립트 의 함수 정의는 다른 함수 정의의 본문에 직접 중첩 될 수 있으므로 논란의 여지 가 있다고 생각합니다. 구별 할 가치가 없습니다. (또는 이것이 Java 프로그래밍에서 인기있는 스타일 일 수 있습니다. 메소드는 OTBS가 아니라 동일한 행에서 여는 중괄호를 가져옵니다.) 어느 방법을 사용하든 구문이 중괄호 배치에 엄격한 제약 조건을 적용하여 작동하는 방법에 대한 훌륭한 지적을합니다. 전혀 ()없거나 그것과 비슷한 것.
Eliah Kagan
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.