zshでは、path
内容はよく知られている変数に関連付けられている特別な配列変数ですPATH
。
実際、この関数を定義して呼び出すことは非常に特別です。
f() { local -r path=42 }
エラーが発生しますf: read-only variable: path
。ローカル変数が変更可能であると宣言されると(つまり、not -r
)、すべてが期待どおりに機能します。別の変数名を使用すると、このエラーを再現できません。
このエラーはなぜ発生しますか?意図的なことでしょうか?他の名前にも同様の規則がありますか?
私はmacOS 10.12.6でzsh 5.2(x86_64-apple-darwin16.0)を使用しています。
答え1
TL;DR「特別な組み込みパラメータ」を再使用しないでくださいpath
。または、メーリングリストこの-h
フラグは次のように使用できます。
% () { local -hr path=42; echo $path }
42
%
(しかし、整数に変更すると、このオーバーライドを忘れてしまう...と仮定するpath
後続のコードが混乱する可能性があります。)path
path
より長い発掘が続きました(しかし-h
隠されたものを完全に逃しました...)
% print ${(t)path}
array-special
これは特殊変数(関数?エラー?)の属性ですが、ユーザーリンクの同様の変数ではありません。
% () { typeset -r PATH=/blah; echo $PATH }
(anon): read-only variable: PATH
% typeset -Tar FOO=bar foo
% print $foo
bar
% print ${(t)foo}
array-readonly-tag_local
% () { local -r foo=blah; echo $foo }
blah
この動作を表すさまざまなパラメータがあります。
% for p in $parameters[(I)*]; do print $p $parameters[$p]; done | grep array-
cdpath array-special
...
% () { local -r cdpath=42 }
(anon): read-only variable: cdpath
したがって、いくつかの変数は次のようになります。動物農場他の人よりも特別です。このエラーメッセージはさまざまな場所で発生し、その中でSrc/params.c
コンパイル時に見つかったメッセージが特定であるかどうかを印刷するように修正すると、次のようになりますzsh
。
% () { local -r path }
% () { local -r path=foo }
(anon): read-only variable (setarrvalue): path
かなり一般的なコードです
/**/
mod_export void
setarrvalue(Value v, char **val)
{
if (unset(EXECOPT))
return;
if (v->pm->node.flags & PM_READONLY) {
zerr("read-only variable (setarrvalue): %s", v->pm->node.nam);
freearray(val);
return;
}
これは、問題が他の場所で発生することを示します。非特殊変数は間違いなくPM_READONLY
設定されていませんが、失敗した特殊変数は設定されました。次に注目すべき点は、local
さまざまな名前(...)を持つコードですtypeset
export
。これらはすべて組み込まれているので、画面に何が隠れているかを見つけることができます。Src/builtin.c
% grep BUILTIN Src/builtin.c | grep local
BUILTIN("local", BINF_PLUSOPTS | BINF_MAGICEQUALS | BINF_PSPECIAL | BINF_ASSIGN, (HandlerFunc)bin_typeset, 0, -1, 0, "AE:%F:%HL:%R:%TUZ:%ahi:%lp:%rtux", NULL),
これはbin_typeset
さまざまなフラグを設定する呼び出しなので、関数のソースコードを見てみましょう。コメントで誓い、確認してください。状況が複雑なので確認してみてください。ウサギの洞窟にもかかわらず(「パラメータをパターンとして処理」-m
オプションが選択されている場合)いいえset、ここの場合)このtypeset_single
関数の結果のようです...
POSIXBUILTINS
関連するコードがありますが、readonly
私のテストシェルでは閉じています。
% print $options[POSIXBUILTINS]
off
だから私はそのコードを無視します。同時に!一部のデバッグポイントは、次の行でPM_READONLY
フラグがオンになっていることを示します。path
/*
* The remaining on/off flags should be harmless to use,
* because we've checked for unpleasant surprises above.
*/
pm->node.flags = (PM_TYPE(pm->node.flags) | on | PM_SPECIAL) & ~off;
これはon
、関数を入力したときにすでに開いている変数からのものです。ため息、始まった場所typeset_single
に戻ります...まあ、デフォルトでは、ユーザーが次のように変数を提供したときに、代わりにいくつかのマクロを介してデフォルトで有効になる変数があります。 thisコードパスが実行されると、変数はオフになり、すべてがうまく機能します。bin_typeset
TYPESET_OPTSTR
PM_READONLY
PM_READONLY
path
たとえば、特殊変数が読み取り専用になるように(zsh-workersメーリングリストを使用してみてください)、そうでなければその間に特殊変数を操作しないように変更できるかどうかはZSH開発者に質問です。