zsh 구문이란 무엇입니까? 이름() 참

zsh 구문이란 무엇입니까? 이름() 참

다음 블록이 함수를 나타낸다고 가정하지만 아마도 그렇지 않을 것입니다.

mounted()true
if
  ...
fi ... && mounted

이 구조가 무엇인지 이해하고 싶습니다. 함수 헤더에서 유사한 구문을 찾지 못했습니다. 다루기 힘든

실제 코드의 보다 완전한 스니펫은 다음과 같습니다.

#! /bin/zsh -p

# leaving out a section...

tmpdir=$(mktemp -d) || exit

mounted()true
if
  mount "$type[@]" -o "${(j[,])opts}" -- "$dev" "$tmpdir"
then
  mount --bind -- "$tmpdir/$subdir" "$dest" || mounted()false
  umount -- "$tmpdir"
fi && rmdir -- "$tmpdir" && mounted

일단 이해하고 나면 전체 zsh 스크립트를 나에게 더 친숙한 언어로 변환합니다. 중간 단계로 bash로 변환할 수도 있습니다.

답변1

이것은 함수 정의를 위한 Bourne 쉘 구문(1980년대)이며 zsh에만 국한되지 않습니다.

Bourne 쉘에서 함수는 functionName()명령 앞에 붙여넣는 방식으로 정의됩니다.

name() true그래서 간단한 명령으로 호출되는 함수를 본문으로 정의합니다 .nametrue

$ name()true
$ type name
name is a shell function

이는 거의 모든 Bourne 유사 쉘(ksh, ash, dash, bosh, pdksh, mksh, zsh...)의 경우입니다. 주목할만한 예외 중 하나는 bash²(GNU 쉘)입니다. 처음에는명령 그룹( { ...; })는 함수 본문이 되었고 나중에 다음과 같이 변경되었습니다.모든 복합 명령~처럼POSIX sh언어 요구사항.

따라서 에서는 또는 ( 및 ksh에서 빌린 구문)이 복합 명령으로 처리됩니다. 또는 bash함수 본문이 하나의 간단한 명령만 포함하는 명령 그룹입니다.name()((1))name()[[ . ]](( ... ))[[ ... ]]name() { true; }

ksh비록 구문은 다르지만 이는 함수를 도입하는 첫 번째 셸입니다 function name { body; }. zshKorn 및 Bourne 구문을 지원하며 자체 확장 기능이 있습니다.

에서 Korn에 대한 섹션으로 연결됩니다 zsh.info zsh functionfunction핵심 단어함수 정의 구문. 확장 중 하나는 zsh동일한 본문을 사용하여 여러 함수를 동시에 정의하고 임의의 문자열을 함수 이름으로 사용할 수 있다는 것입니다.

vrai 1 + $'\1' () true
faux 0 - $'\0' '' () false

호출되거나 매개변수를 사용하지 않는 몇 가지 다른 함수를 정의 true합니다 false.

함수 이름을 생략하면 인수를 받아들이고 그 자리에서 호출할 수 있는 익명 함수가 됩니다.

() { echo There are $# non-hidden txt files; } *.txt(N)

(분명한 이유로 익명 함수가 인수를 받아들이기 위해서는 그 본문이 간단한 명령이 될 수 없습니다.)

에서는 키가 함수 이름이고 값이 본문의 코드인 zsh특수 연관 배열을 통해서도 함수를 사용할 수 있습니다 . 함수를 정의하는 다른 방법도 마찬가지입니다 .$functionsfunctions[name]=truename


이제 부울 값을 저장하기 위해 함수를 사용하는 것이 일반적이지 않지만 잠시 멈춰서 생각해 보면 의미가 있습니다.

예를 들어 C 언어에서 if/ while구문 또는 &&/ ||논리 연산자는 숫자에 적용됩니다. 0이 아닌 숫자이면 if (condition) something실행합니다. 또는 어떤 C 유사 언어가 이를 정의 또는 비어 있지 않은 문자열로 확장합니다.somethingconditionawkperlcondition

그러나 쉘은 모든 명령줄 해석기보다 우선합니다. 쉘에서는 모든 것이 명령입니다. if/ while&&/는 ||대부분의 쉘에서 명령에 따라 작동합니다. 명령이 성공하면 if condition; then something; fi실행됩니다 .somethingcondition

falsetrue항상 실패/성공하는 부울 상수 명령(대부분의 쉘에 내장되어 있음)이므로 부울 값을 나타내는 확실한 명령입니다. 함수는 명령(또는 일반적으로 쉘 코드)을 저장하는 데 가장 적합한 데이터 구조입니다.

aliases(많은 사람들이 csh를 손상된 상속으로 간주하고 csh는 함수가 없는 쉘(원래 Bourne 쉘과 같은)임)는 별칭이 포함된 코드를 읽을 때 확장되고 런타임 시 확장되지 않기 때문에 여기서 작동하지 않습니다. 예를 들어:

alias name=false
myfunction()
  if name; then
    something
  fi
alias name=true
myfunction

함수가 실행될 때가 아니라 함수를 정의하는 코드를 읽을 때 별칭이 확장되기 if false; then...때문에 함수 본문이 실제로 포함됩니다 .name

코드는 함수 대신 변수에 저장할 수 있습니다.

name=true name=false
if eval " $name"; then
  ...
fi

4eval 에서 코드를 설명하라는 명령의 성공 여부를 테스트합니다 . 이 경우 비어 있거나 정의되지 않은 결과가 발생합니다(옵션 제외).$namenounset$name진짜.

아니면 이렇게 할 수도 있습니다(이것이 제가 보통 sh/ 스크립트 bash에서 하는 일입니다):

name=true name=false
if "$name"; then
  ...
fi

$name인수 없이 명령 에 저장된 이름을 실행하는 곳입니다.

또는:

name=(true) name=(false)
if "${name[@]}"; then
  ...
fi

매개변수를 저장하는 곳간단한 명령안에$name 대량으로변하기 쉬운.

[C와 유사한 언어 작업에 익숙한 사람들은 부울 값을 정수 변수로 저장하고 /etc와 같은 명령을 실행하거나 test텍스트 expr표현에서 변환한 후 정수 값을 테스트할 수 있습니다.

false=0 true=1
name=$false name=$true

if expr "$name" > /dev/null; then
  ...
fi
if [ "$name" -ne 0 ]; then
  ...
fi

Korn과 유사한 셸( bash및 포함)에서는 C와 유사한 산술 표현식을 평가하고 0이 아닌 숫자(NaN 포함)가 생성될 때 성공을 반환하는 구문을 zsh사용할 수 있습니다 .((...))

false=0 true=1
name=$false name=$true
# or even:
name=false name=true
if (( name )); then
  ...
fi

또한 명령을 실행하여 문자열을 비교하거나(예: [// testagain ) expr다른 Korn 유사 구성 [[ string = pattern ]]과 같이 패턴 일치를 수행할 수 있습니다 .

name=true name=false
if [ "$name" = true ]; then
  ...
fi

(이것은 C에서 작업하는 것만큼 나에게 이질적입니다 if (strcmp(name, "true") == 0)....)

또는 원한다면 이미 정의된 변수에 대해 awk/와 같은 테스트를 수행할 수도 있습니다.perl

unset -v name # unset = false
name=         #   set = true
if [ -n "${name+true}" ]; then
  ...
fi

1 Bourne 셸(복제/파생 5 아님)에 버그가 있지만 함수 본문으로 리디렉션이 포함된 간단한 명령을 사용하면 작동하지 않습니다. 이것이 아마도 POSIX에서 복합 명령만 필요한 이유일 것입니다. 함수 본문으로 지원됨 .

² yash(POSIX 사양에 따라 작성됨) posh( pdksh표준을 준수하는지 확인하는 데 도움이 되도록 작성되었으므로 이를 포함하여 표준에 대한 대부분의 확장이 제거됨)는 다른 두 가지 예외입니다.

³ 이는 파일에 모든 문자열이 포함될 수 있기 때문에 외부 명령과 명령 인수가 어떤 문자열일 수도 있다는 사실과 일치합니다(단, 파일 이름은 비워 둘 수 없고 파일 이름/인수에는 NUL 바이트를 포함할 수 없습니다). Bourne 쉘에서 함수와 변수 이름은 동일한 네임스페이스를 공유하며(동일한 이름을 가진 함수와 변수는 정의할 수 없음) 함수 이름에는 변수 이름과 동일한 제한 사항이 있습니다.

4 일부 구현에서는 옵션 끝 표시를 eval지원하지 않으므로 정확성을 위해 선행 공백이 추가되었습니다.--

5 zsh 자체에는 함수 본문에서 리디렉션을 사용할 때 자체적인 문제가 있었지만 대부분이 해결되었습니다. 그러나 지금도 문서에 명확하게 나와 있듯이 f() { cmd; } < $1(본문이 리디렉션이 있는 명령 그룹인 특수한 경우) 함수 범위를 $1참조 하지 않고 POSIX 표준을 준수하지 않게 만드는 호출자의 해당 인스턴스를 참조합니다. . 이는 단순 명령이나 기타 유형의 복합 명령( 내부적으로 포함됨 ) 에는 적용되지 않습니다 .$1$1zsh{...}

관련 정보