다음 블록이 함수를 나타낸다고 가정하지만 아마도 그렇지 않을 것입니다.
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
그래서 간단한 명령으로 호출되는 함수를 본문으로 정의합니다 .name
true
$ 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; }
. zsh
Korn 및 Bourne 구문을 지원하며 자체 확장 기능이 있습니다.
에서 Korn에 대한 섹션으로 연결됩니다 zsh
.info zsh function
function
핵심 단어함수 정의 구문. 확장 중 하나는 zsh
동일한 본문을 사용하여 여러 함수를 동시에 정의하고 임의의 문자열을 함수 이름으로 사용할 수 있다는 것입니다.
vrai 1 + $'\1' () true
faux 0 - $'\0' '' () false
호출되거나 매개변수를 사용하지 않는 몇 가지 다른 함수를 정의 true
합니다 false
.
함수 이름을 생략하면 인수를 받아들이고 그 자리에서 호출할 수 있는 익명 함수가 됩니다.
() { echo There are $# non-hidden txt files; } *.txt(N)
(분명한 이유로 익명 함수가 인수를 받아들이기 위해서는 그 본문이 간단한 명령이 될 수 없습니다.)
에서는 키가 함수 이름이고 값이 본문의 코드인 zsh
특수 연관 배열을 통해서도 함수를 사용할 수 있습니다 . 함수를 정의하는 다른 방법도 마찬가지입니다 .$functions
functions[name]=true
name
이제 부울 값을 저장하기 위해 함수를 사용하는 것이 일반적이지 않지만 잠시 멈춰서 생각해 보면 의미가 있습니다.
예를 들어 C 언어에서 if
/ while
구문 또는 &&
/ ||
논리 연산자는 숫자에 적용됩니다. 0이 아닌 숫자이면 if (condition) something
실행합니다. 또는 어떤 C 유사 언어가 이를 정의 또는 비어 있지 않은 문자열로 확장합니다.something
condition
awk
perl
condition
그러나 쉘은 모든 명령줄 해석기보다 우선합니다. 쉘에서는 모든 것이 명령입니다. if
/ while
및 &&
/는 ||
대부분의 쉘에서 명령에 따라 작동합니다. 명령이 성공하면 if condition; then something; fi
실행됩니다 .something
condition
false
및 true
항상 실패/성공하는 부울 상수 명령(대부분의 쉘에 내장되어 있음)이므로 부울 값을 나타내는 확실한 명령입니다. 함수는 명령(또는 일반적으로 쉘 코드)을 저장하는 데 가장 적합한 데이터 구조입니다.
alias
es(많은 사람들이 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
에서 코드를 설명하라는 명령의 성공 여부를 테스트합니다 . 이 경우 비어 있거나 정의되지 않은 결과가 발생합니다(옵션 제외).$name
nounset
$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
또한 명령을 실행하여 문자열을 비교하거나(예: [
// test
again ) 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
$1
zsh
{...}