# パラメータと変数

パラメータとは、​パラメータ展開で値に置き換えられるデータを言います。パラメータには位置パラメータ・特殊パラメータ・変数の三種類があります。

## 位置パラメータ

位置パラメータは 1 以上の自然数によって識別されるパラメータです。例えば位置パラメータが三つある場合、それらは順に `1`, `2`, `3` という名称で識別されます。位置パラメータの個数は特殊パラメータ `#` で取得できます。また全ての位置パラメータを表す特殊パラメータとして `*` と `@` があります。

位置パラメータは、シェルの起動時に、シェルのコマンドライン引数を元に初期化されます (起動時のコマンドライン引数参照)。引数のうち、位置パラメータの値として与えられたオペランドが順に一つずつ位置パラメータとなります。

シェルのコマンド実行中に​関数が呼び出されるとき、位置パラメータはその関数の呼び出しに対する引数に変更されます。すなわち、関数の実行中は位置パラメータによって関数の引数を参照できます。関数呼び出しの直前の位置パラメータの値は保存されており、関数の実行が終了する際に元の値に戻ります。

位置パラメータは、​set や shift などの組込みコマンドによって変更できます。

`0` は位置パラメータとは見なされません (特殊パラメータの一つです)。

## 特殊パラメータ

特殊パラメータは一文字の記号によって識別されるパラメータです。特殊パラメータにはユーザが明示的に値を代入することはできません。

Yash では以下の特殊パラメータが利用可能です。

`0`

  このパラメータの値は、シェルの起動時に与えられたシェルの実行ファイルの名称またはスクリプトファイルの名称です。(起動時のコマンドライン引数参照)

`#`

  このパラメータの値は、現在の位置パラメータの個数を表す 0 以上の整数です。

`$`

  このパラメータの値は、シェル自身のプロセス ID を表す正の整数です。この値はサブシェルにおいても変わりません。

`-`

  このパラメータの値は、現在シェルで有効になっているオプションの文字をつなげたものです。この値には、​シェルの起動時にコマンドライン引数で指定できる一文字のオプションのうち現在有効になっているものが全て含まれます。​Set 組込みコマンドでオプションを変更した場合は、その変更がこのパラメータの値にも反映されます。

`?`

  このパラメータの値は、最後に終了した​パイプラインの終了ステータスを表す 0 以上の整数です。

`!`

  このパラメータの値は、最後に実行した​非同期コマンドのプロセス ID です。

`*`

  このパラメータの値は、現在の位置パラメータの値です。位置パラメータが一つもない場合、このパラメータの値は空文字列です。位置パラメータが複数ある場合、このパラメータの値は全ての位置パラメータの値を連結したものです。各位置パラメータの値の間は以下に従って区切られます。

  - 変数 `IFS` が存在し、その値が空でない場合、各位置パラメータは変数 `IFS` の値の最初の文字で区切られます。

  - 変数 `IFS` が存在し、その値が空の場合、各位置パラメータは間に何も置かずに連結されます。

  - 変数 `IFS` が存在しない場合、各位置パラメータは空白文字で区切られます。

  このパラメータの展開結果に対して​単語分割が行われる場合、値はまず元の位置パラメータに一致するように分割されさらに変数 `IFS` の値に従って分割されます。この最初の分割は `IFS` が空文字列でも行います。

`@`

  このパラメータは、パラメータ `*` と同様に現在の全ての位置パラメータを表します。ただし、このパラメータが二重引用符による​クォートの中で​展開される場合の扱いがパラメータ `*` と異なります。この場合、結果は各位置パラメータに正確に一致するように​単語分割されます。また位置パラメータが一つもない場合、このパラメータは展開後の単語には残りません。(よって、引用符の中であるにもかかわらず、展開結果は一つの単語になるとは限りません。)

  例えば位置パラメータが一つもないとき、コマンドライン `echo 1 "$@" 2` は `echo`、`1`、`2` という三つの単語に展開されます。位置パラメータが `1`、`2 2`、`3` の三つのとき、コマンドライン `echo "$@"` は `echo`、`1`、`2 2`、`3` という四つの単語に展開され、コマンドライン `echo "a$@b"` は `echo`、`a1`、`2 2`、`3b` という四つの単語に展開されます。

## 変数

変数とはユーザが自由に代入可能なパラメータです。各変数は名前で区別され、それぞれが文字列の値を持ちます。

変数の名前は、英数字と下線 (`_`) から構成されます。ただし変数名の頭文字を数字にすることはできません。環境によってはこれ以外の文字も変数名に使用できます。

シェルが扱う変数のうち、エクスポートの対象となっているものは環境変数といいます。これらの変数はシェルが外部コマンドを起動する際に外部コマンドに渡されます。シェルが起動されたときにシェルを起動したプログラムから渡された変数は自動的に環境変数になります。

変数は、​単純コマンドによって代入できます。また typeset 組込みコマンドなどでも変数に代入することができます。変数を削除するには unset 組込みコマンドを使います。

### シェルが使用する変数

以下の名前の変数は、yash の実行において特別な意味を持っています。

`CDPATH`

  この変数は cd 組込みコマンドで移動先ディレクトリを検索するために使われます。

`COLUMNS`

  この変数は端末ウィンドウの横幅 (文字数) を指定します。この変数が設定されている場合、デフォルトの横幅ではなくこの変数の値で指定された横幅が​行編集で使われます。

`COMMAND_NOT_FOUND_HANDLER`

  シェルが実行しようとしたコマンドが見つからなかったとき、この変数の値がコマンドとして実行されます。不明なコマンドを実行したときに何か別のコマンドを実行させたい時に便利です。​単純コマンドの実行を参照。

  この機能は POSIX 準拠モードでは働きません。

`DIRSTACK`

  この配列変数はディレクトリスタックの実装に使われています。​pushd 組込みコマンドでディレクトリを移動したとき、前のディレクトリを覚えておくためにそのパス名がこの配列に入れられます。この配列の内容を変更することは、ディレクトリスタックの内容を直接変更することになります。

`ECHO_STYLE`

  この変数は echo 組込みコマンドの挙動を指定します。

`ENV`

  POSIX 準拠モードで対話モードのシェルが起動されたとき、この変数の値で示されるパスのファイルが初期化スクリプトとして読み込まれます (シェルの初期化処理参照)。

`FCEDIT`

  Fc 組込みコマンドでコマンドを編集する際、この変数の値で示されたエディタがコマンドの編集に使われます。

`HANDLED`

  この変数は `COMMAND_NOT_FOUND_HANDLER` 変数の値が実行された後に、コマンドが見つからなかったことをエラーとするかどうかを指示します。​単純コマンドの実行を参照。

`HISTFILE`

  コマンド履歴を保存するファイルのパスを指定します。

`HISTRMDUP`

  コマンド履歴の重複をチェックする個数を指定します。履歴にコマンドを追加する際、既に履歴にあるコマンドのうちここで指定した個数のコマンドが新しく追加されるコマンドと同じかどうかをチェックします。同じコマンドが既に履歴にあれば、それは履歴から削除されます。

  例えばこの変数の値が `1` のときは、履歴に追加されるコマンドが一つ前のコマンドと同じならばそれは削除されます。それより古い履歴のコマンドは、(履歴に追加されるコマンドと同じでも) 削除されません。もしこの変数の値が `HISTSIZE` 変数の値と同じなら、履歴の中で重複するコマンドはすべて削除されます。あるいはもしこの変数の値が `0` なら、重複する履歴は一切削除されません。

`HISTSIZE`

  コマンド履歴に保存される履歴項目の個数を指定します。

`HOME`

  ユーザのホームディレクトリのパスを指定します。​チルダ展開や cd 組込みコマンドの動作に影響します。

`IFS`

  この変数は​単語分割の区切りを指定します。シェルの起動時にこの変数の値は空白文字・タブ・改行の三文字に初期化されます。

`LANG`
`LC_ALL`
`LC_COLLATE`
`LC_CTYPE`
`LC_MESSAGES`
`LC_MONETARY`
`LC_NUMERIC`
`LC_TIME`

  これらの変数はシェルが動作するロケールを指定します。シェルが読み書きするファイルのエンコーディングやエラーメッセージの内容などはこの変数で指定されたロケールに従います。

  `LC_CTYPE` 変数の値はシェルの起動時にのみ反映されます。シェルの実行中にこの変数を変更してもシェルのロケールは変わりません (シェルが非 POSIX 準拠モードで​対話モードの場合を除く)。

`LINENO`

  この変数の値は、現在シェルが読み込んで実行しているファイルにおける、現在実行中のコマンドのある行番号を示します。(対話モードでは、コマンドを入力して実行するたびに行番号は 1 に戻ります)

  一度この変数に代入したり変数を削除したりすると、この変数を用いて行番号を取得することはできなくなります。

`LINES`

  この変数は端末ウィンドウの行数を指定します。この変数が設定されている場合、デフォルトの行数ではなくこの変数の値で指定された行数が​行編集で使われます。

`MAIL`

  この変数は​メールチェックの対象となるファイルのパスを指定します。

`MAILCHECK`

  この変数は​メールチェックを行う間隔を秒単位で指定します。この変数の値はシェルの起動時に `600` に初期化されます。

`MAILPATH`

  この変数は​メールチェックの対象となるファイルのパスを指定します。

`NLSPATH`

  POSIX によるとこの変数の値はロケール依存のメッセージデータファイルのパスを指示することになっていますが、yash では使用していません。

`OLDPWD`

  Cd 組込みコマンドなどで作業ディレクトリを変更したときに、変更前の作業ディレクトリパスがこの変数に設定されます。この変数はデフォルトでエクスポート対象になります。

`OPTARG`

  Getopts 組込みコマンドで引数付きのオプションを読み込んだとき、その引数の値がこの変数に設定されます。

`OPTIND`

  この変数の値は、​getopts 組込みコマンドで次に読み込むオプションのインデックスを表します。シェルの起動時にこの変数は `1` に初期化されます。

`PATH`

  この変数は、​コマンドの検索時にコマンドのありかを示すパスを指定します。

`PPID`

  この変数の値は、シェルの親プロセスのプロセス ID を表す正の整数です。この変数はシェルの起動時に初期化されます。この変数の値は​サブシェルにおいても変わりません。

`PROMPT_COMMAND`

  POSIX 準拠モードでない​対話モードのシェルにおいて、シェルが各コマンドのプロンプトを出す直前に、この変数の値がコマンドとして解釈・実行されます。これは、プロンプトを出す直前に毎回 `eval -i -- "${PROMPT_COMMAND-}"` というコマンドが実行されるのと同じですが、このコマンドの実行結果は次のコマンドでの `?` 特殊パラメータの値には影響しません。

`PS1`

  この変数の値は、対話モードのシェルが出力する標準のコマンドプロンプトを指定します。この値の書式については​プロンプトの項を参照してください。

  この変数はシェルの起動時に実効ユーザ ID が 0 かどうかによって `$` と `#` のどちらかに初期化されます。

`PS1P`

  この変数の値は、対話モードのシェルがコマンドを読み込む際に、​推定されたコマンドを表示するフォントの書式を指定します。この値の書式については​プロンプトの項を参照してください。

`PS1R`

  この変数の値は、対話モードのシェルがコマンドを読み込む際に、入力されるコマンドの右側に表示されるプロンプトを指定します。この値の書式については​プロンプトの項を参照してください。

`PS1S`

  この変数の値は、対話モードのシェルがコマンドを読み込む際に、入力されるコマンドを表示するフォントの書式を指定します。この値の書式については​プロンプトの項を参照してください。

`PS2`

  この変数の値は、対話モードのシェルが出力する補助的なコマンドプロンプトを指定します。この値の書式については​プロンプトの項を参照してください。 この変数はシェルの起動時に `>` に初期化されます。

`PS2P`

  この変数は `PS1P` 変数と同様ですが、プロンプトとして `PS1` 変数ではなく `PS2` 変数の値が使用されるときに使用されます。

`PS2R`

  この変数は `PS1R` 変数と同様ですが、プロンプトとして `PS1` 変数ではなく `PS2` 変数の値が使用されるときに使用されます。

`PS2S`

  この変数は `PS1S` 変数と同様ですが、プロンプトとして `PS1` 変数ではなく `PS2` 変数の値が使用されるときに使用されます。

`PS4`

  Xtrace オプションが有効なとき、この変数の値が各トレース出力の前に出力されます。ただし出力の前にこの変数の値に対して​パラメータ展開、​コマンド置換、​数式展開を行います。また POSIX 準拠モードでなければ、`PS1` 変数と同様に、バックスラッシュで始まる特殊な記法が利用できます。

  この変数はシェルの起動時に `+` に初期化されます。

`PS4S`

  この変数は `PS1S` 変数と同様ですが、プロンプトとして `PS1` 変数が使用されるときではなく、トレース出力の際に `PS4` 変数の値が使用されるときに使用されます。この変数を使うとトレース出力のフォントの書式を変更することができます。

`PWD`

  この変数の値は現在の作業ディレクトリの絶対パスを表します。この変数はシェルの起動時に正しいパスに初期化され、​cd 組込みコマンドなどで作業ディレクトリを変更する度に再設定されます。この変数はデフォルトでエクスポート対象になります。

`RANDOM`

  この変数は乱数を取得するために使用できます。この変数の値は 0 以上 32768 未満の一様分布乱数になっています。

  この変数に非負整数を代入すると乱数を生成する種を再設定できます。

  一度この変数を削除すると、この変数を用いて乱数を取得することはできなくなります。またシェルが POSIX 準拠モードで起動された場合、この変数で乱数を取得することはできません。

`TERM`

  この変数は対話モードのシェルが動作している端末の種類を指定します。ここで指定された端末の種類に従って​行編集機能は端末を制御します。この変数の効力を得るためには変数がエクスポートされている必要があります。

`YASH_AFTER_CD`

  この変数の値は、​cd 組込みコマンドや pushd 組込みコマンドで作業ディレクトリが変更された後にコマンドとして解釈・実行されます。これは、作業ディレクトリが変わった後に毎回 `eval -i -- "${YASH_AFTER_CD-}"` というコマンドが実行されるのと同じです。

`YASH_LOADPATH`

  ドット組込みコマンドで読み込むスクリプトファイルのあるディレクトリを指定します。`PATH` 変数と同様に、コロンで区切って複数のディレクトリを指定できます。この変数はシェルの起動時に、yash に付属している共通スクリプトのあるディレクトリ名に初期化されます。

`YASH_LE_TIMEOUT`

  この変数は​行編集機能で曖昧な文字シーケンスが入力されたときに、入力文字を確定させるためにシェルが待つ時間をミリ秒単位で指定します。行編集を行う際にこの変数が存在しなければ、デフォルトとして 100 ミリ秒が指定されます。

`YASH_PS1`
`YASH_PS1P`
`YASH_PS1R`
`YASH_PS1S`
`YASH_PS2`
`YASH_PS2P`
`YASH_PS2R`
`YASH_PS2S`
`YASH_PS4`
`YASH_PS4S`

  POSIX 準拠モードではないとき、これらの変数は名前に `YASH_` が付かない `PS1` 等の変数の代わりに優先して使われます。POSIX 準拠モードではこれらの変数は無視されます。​プロンプトで yash 固有の記法を使用する場合はこれらの変数を使用すると POSIX 準拠モードで yash 固有の記法が解釈されずに表示が乱れるのを避けることができます。

`YASH_VERSION`

  この変数はシェルの起動時にシェルのバージョン番号に初期化されます。

### 配列

配列とは、一つの変数に複数の値 (文字列) を持たせたものです。一つの配列の複数の値は位置パラメータと同様に 1 以上の自然数で識別されます。

配列は、​単純コマンドによって代入できます。また array 組込みコマンドなどでも配列に代入することができます。配列を削除するには変数と同様に unset 組込みコマンドを使います。

配列を配列のままエクスポートすることはできません。配列をエクスポートしようとすると、配列の各値をコロンで区切って繋いだ一つの文字列の値を持つ変数としてエクスポートされます。

POSIX 準拠モードでは配列は使えません。