次のブロックが関数を表すと仮定しますが、おそらくそうではありません。
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 ...)の場合です。注目すべき例外の1つはbash
²(GNUシェル)です。最初はコマンドグループ({ ...; }
)は関数の本文になり、後で次のように変更されました。すべての複合コマンド〜のようにPOSIXsh
言語要件。
したがって、または(およびkshから借りた構文)は複合コマンドとして扱われます。または、bash
関数の本文が1つの単純なコマンドのみを含むコマンドのグループです。name()((1))
name()[[ . ]]
(( ... ))
[[ ... ]]
name() { true; }
ksh
構文は異なりますが、これは関数を導入する最初のシェルですfunction name { body; }
。zsh
KornとBourneの構文をサポートし、独自の拡張機能があります。
からKornのセクションにリンクされていますzsh
。info zsh function
function
キーワード関数定義構文。拡張の1つは、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
構文または&&
/||
論理演算子が数値に適用されます。ゼロ以外の数値であれば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に似た算術式を評価し、ゼロ以外の数値(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
標準に準拠していることを確認するのに役立つように書かれているため、それらを含む標準へのほとんどの拡張は削除されます)は、他の2つの例外です。
³これは、ファイルに任意の文字列を含めることができるため、外部コマンドとコマンド引数が任意の文字列である可能性があるという事実と一致します(ただし、ファイル名は空白にできず、ファイル名/引数にはNULバイトを含めることはできません)。 Bourneシェルでは、関数と変数名は同じ名前空間を共有します(同じ名前の関数と変数は定義できません)、関数名には変数名と同じ制限があります。
4一部の実装ではオプションの終わり表示をサポートeval
していないため、精度のために先行スペースを追加しました。--
5 zsh自体には、関数の本文でリダイレクトを使用するときに独自の問題がありましたが、ほとんどが解決されました。しかし、今でも文書に明確に示されているようにf() { cmd; } < $1
(本文がリダイレクトを持つコマンドグループである特別な場合)、関数のスコープを参照せずに$1
POSIX標準に準拠しないようにする呼び出し元の対応するインスタンスを参照します。 。これは、単純なコマンドや他の種類の複合コマンド(内部的に含まれています)には適用されません。$1
$1
zsh
{...}