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


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

대안 bash은function

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.