sh의 함수에 0개의 명령문이 있을 수 있나요?

sh의 함수에 0개의 명령문이 있을 수 있나요?

sh구현이 빈 함수로 수행해야 하는 작업을 명시하는 관련 표준이 있나요 ?

다음 코드 조각은 문이 없는 함수를 정의합니다.

a() {
}

서브쉘 버전도 동일하게 취급되는 것 같습니다.

a() (
)

ashzsh아무것도 하지 않고 종료 상태가 0인 함수로 모든 구성을 허용합니다 .

ksh( ksh93) 및 bash둘 다 구문 오류로 함수를 거부합니다.

$ a() {
> }
ksh: syntax error: `}' unexpected

그리고 배쉬

bash-4.4$ a() {
> }
bash: syntax error near unexpected token `}'

답변1

아니요, 적합한 애플리케이션에서는 함수의 중괄호 사이에 빈 함수 본문이 있을 수 없습니다.


POSIX기능 정의 명령 정의처럼:

fname ( ) compound-command [io-redirect ...]

이 단어는 모두 사양의 다른 곳에서 정의된 항목에 대한 자리 표시자입니다. compound-command함수 본문입니다.

복합 명령다음과 같이 정의됩니다.루프, 조건문, 사례문을 포함한 여러 항목 중 하나이지만 여기서 가장 관련성이 높은 항목은 다음과 같습니다.그룹화 명령, 두 가지 경우로 정의됨:

( compound-list )

서브셸 환경에서 복합 목록을 실행합니다. 셸 실행 환경을 참조하세요. 환경에 영향을 미치는 변수 할당 및 내장 명령은 목록 끝까지 남아 있어서는 안 됩니다. (...산술 확장에 관한 단락이 생략되었습니다...)

{ compound-list ; }

현재 프로세스의 컨텍스트에서 화합물 목록을 실행합니다. 여기에 표시된 세미콜론은 } 예약어를 구분하는 제어 연산자의 예입니다. 셸 구문에 표시된 것처럼 다른 구분 기호도 가능합니다. <newline>이 자주 사용됩니다.

비어 있을 수 있으면 빈 {\n}본문이 유효합니다.compound-list

이것쉘 구문이는 다음을 포함하여 쉘 명령 언어의 구문 분석 규칙을 추가로 정의합니다.화합물 목록:

compound_list    : linebreak term
                 | linebreak term separator

즉, 화합물 목록 linebreak뒤에는 a term또는 linebreaka term및 a 가 옵니다 separator. separatorIs ;또는 &. linebreak은 빈 개행 시퀀스일 수 있습니다. 따라서 null 이 될 수 있으면 null 이 될 수 있습니다 term.

term예:

term             : term separator and_or
                 |                and_or

그리고 and_or:

and_or           :                         pipeline
                 | and_or AND_IF linebreak pipeline
                 | and_or OR_IF  linebreak pipeline

마지막 두 줄은 &&합계를 다룹니다 ||. 문자로 구분된 비어 있지 않은 s 시퀀스입니다 pipeline. 간단한 명령, 복합 명령 또는 기능 정의입니다. 따라서 단순 명령이나 복합 명령이 null이 될 수 있는 경우 , 및 는 null이 될 수 있습니다.command|commandtermcommand

cmd_name단순 명령에는 항상 cmd_word, 또는 중 하나가 포함됩니다 cmd_prefix. cmd_prefix선택적으로 다른 접두사에 추가되는 리디렉션 또는 할당입니다. 나머지 두 개는 둘 다 WORD단어 문자의 비어 있지 않은 시퀀스인 문법의 토큰으로 확인됩니다. 따라서 간단한 명령은 결코 비어 있지 않습니다.

복합 명령에 대해서는 이미 살펴보았지만 이번에는 구문 관점에서 검토해 보겠습니다. 복합 명령은 중괄호 그룹, 하위 쉘, for또는 while루프 untilif또는 중 하나입니다 case. 이들 모두에는 최소한 고정 단어(예: " for") 또는 (or가 포함되어 있습니다. {따라서 복합 명령은 결코 비어 있지 않습니다.

그러므로 a 는 command결코 비워질 수 없고, 따라서 pipeline결코 비워질 수 없습니다, nor and_or, term또는 compound_list. 이것은 의미한다

{
}

허용되지 않으므로 함수 정의

a() {
}

또한 유효하지 않습니다.


위의 모든 사항은 일관되고 이식 가능한 쉘 스크립트에 적용됩니다. 유효하지 않은 스크립트를 처리하기 위해 구현을 자유롭게 확장할 수 zsh있으며 ash, 그들이 선택한 구현은 합리적이고 편리해 보입니다. Bash, ksh, dash 및 기타 도구는 원하는 기능을 달성하기 위해 보다 미니멀한 경로를 취합니다. 모두 만장일치의 선택이었습니다.

이식 가능한 스크립트는 항상 비어 있지 않은 함수 본문을 제공해야 하지만 (예를 들어) zsh만을 대상으로 하는 스크립트는 그렇지 않습니다.

답변2

다양한 쉘의 구문 트리에 관심이 있으신 것 같습니다. bash의 관련 부분은 다음과 같습니다.https://www.gnu.org/software/bash/manual/bashref.html#Shell-Syntax

함수는 다음과 같이 정의됩니다.1]:

다음 구문을 사용하여 함수를 선언합니다.
name () compound-command [ redirections ]
또는
function name [()] compound-command [ redirections ]

관심 있는 부분은 compound-command다음 중 하나일 수 있다는 것입니다.2]:

• 루프 구성: 반복 작업을 위한 셸 명령입니다.
• 조건부 구조: 조건부 실행에 사용되는 셸 명령입니다.
• 명령 그룹화: 명령을 그룹화하는 방법입니다.

{}구문 ()은 a command grouping이며 다음 중 하나일 수 있습니다.]:

( list )
{ list; }

A는 list다음과 같이 정의됩니다.4]:

‘;’목록은 연산자 , ‘&’또는 중 하나로 구분되고 ‘&&’선택적으로 , ‘||’또는 개행 문자 중 하나로 끝나는 하나 이상의 파이프 시퀀스입니다 .‘;’‘&’

A는 pipline다음과 같이 정의됩니다.5]:

파이프는 제어 연산자 또는 로 ‘|’구분된 하나 이상의 명령 시퀀스 입니다 ‘|&’.

함수 예제에는 하나 이상의 명령을 포함해야 하는 복합 명령이 포함되어 있으며 pipelines각 명령에는 하나 이상의 가 포함되어 있습니다 commands.

따라서 Bash에서는 함수에 최소한 하나의 명령이 있어야 합니다. 다른 쉘도 유사할 수 있으며 구문 가이드를 사용할 수 있습니다.

어떤 이유로든 아무것도 하지 않는 함수를 원한다면 Bash에 내장된 자리 표시자를 사용할 수 있습니다. 즉, :아무 작업도 성공하지 못할 것입니다.

a(){:}

답변3

이것은 bash가 얻을 수 있는 것 중 가장 가까운 것입니다:

a (){  
  :   
}

관련 정보