$ 0が位置パラメータではないのはなぜですか?

$ 0が位置パラメータではないのはなぜですか?

位置パラメータが開始されることを読みました$1(たとえば$1$2などは$3位置パラメータです)。ただし、$0位置パラメータではありません。

しかし、なぜ$0位置パラメータではないのですか?

これが理由かもしれませんが、わかりません。

位置パラメータは、スクリプトが実行されたときにのみその値を持ちます。たとえば./myScript Hello、これは$1価値があるでしょうHello。ただし$0、その値は、スクリプトの実行時(スクリプト名の値を持つ)と、bashスクリプトなしでそれ自体が実行されるとき(bashまたは値を持つこと-bash)の2つの場合に得られます。

答え1

@ikkachuはすでに説明しました私よりも優れています。ただ歴史のメモを追加しています。

Unixの最初のバージョンに付属のシェル(後でThompsonシェルと呼ばれる)には変数はありませんでしたが、すでにパラメータを使用して単純なスクリプトを作成できました。

     sh [ name [ arg1 ... [ arg9 ] ] ]

The name is the name of a file which will be read and in‐
terpreted.   If  not given, this subinstance of the shell
will continue to read the standard input file.

In command lines in the  file  (not  in  command  input),
character  sequences of the form "$n", where n is a digit
0, ..., 9, are replaced by the nth argument to the  invo‐
cation of the shell (argn).  "$0" is replaced by name.

$1...$nは(最初の引数ではありません)すでに$0スクリプトの引数と名前ですが、呼び出されません。位置パラメータそれから。

その時点で、$1シェルで解釈される前に実際に最初の引数に置き換えられました。

たとえば、スクリプトには次のものが含まれます。

echo $1

~と呼ばれる

sh script 'foo; echo bar'

実行できますecho foo; echo bar。このシェルは、数百KBのメモリを持つコンピュータ用に書かれた非常にシンプルなシェルです。

約10年後(1970年代後半)、BourneシェルはUnixバージョンで登場し、環境やその他の利点を導入しました。

Bourneシェルには、変数とより多くのプログラミング構成が付属しています。

これ位置パラメータ少なくともUnixシェルの場合、この用語はBourneシェルで導入されており、スクリプトで使用されている引数($1まだスクリプト名)と同じことを示します。 Thompsonシェルと同様に、位置引数を使用して最初の9つの引数(to)のみを参照できます(ただし、残りの部分にアクセスするにはShiftまたはループを使用してください)(これはまた、ほとんどの最新実装でNotが必要な理由を説明します。 (逆方向移植性)。$n$0$1$9"$@"for i do${10}$10sh

今回はsh script 'foo; echo bar'もうecho bar実行されませんが、Bourneシェルはまだ悪名高いスプリット+globを導入します。これはThompsonシェルとの下位互換性を大幅に損なうことはなく、ファイルリストとしてまだ呼び出すことができますscript 'foo *'。現在のディレクトリから引数として取得します(Thompsonシェルと同じですが、今回は別のメカニズムを使用します)。scriptecho $1echofoo

スクリプトとも呼ばれるシェル(Bourneシェルにはまだ機能がありません):

2.0 Shell procedures

The shell may be used to read and execute commands contained
in a file.  For example,

         sh file [ args  ]

calls the shell to read commands from file.  Such a file  is
called  a  command  procedure or shell procedure.  Arguments
may be supplied with the call and are referred  to  in  file
using  the  positional parameters $1, $2...

機能は1980年代初頭にKornシェル(Bourneシェルベース)に最初に導入されました。

function foo {
  ...
}

通事論。

後で、SysVR2(1984)では、別の構文を使用してBourneシェルに関数も追加されました。

foo() any-command

(ただし、単純なコマンドであり、リダイレクトがある場合、予期しない動作が発生します。これが、おそらくPOSIXが最も一般的に使用されるコマンドなどの複合コマンドのみを認識するようにPOSIXが要求する理由ですany-command。){ ...; }sh

KornおよびBourneシェルでは、関数$0はまだ関数名ではなくスクリプト名です(一方、$1位置$2パラメータは関数パラメータを参照します)。

ksh93これは、関数内で関数名となる関数定義スタイルを変更します。function f {$0

ksh93のように、関数名はどこにzshありますか?匿名機能も導入されました:$0zsh

function { echo $1, $2; } foo bar

または

(){ echo $1, $2; } foo bar

ここでは、構文は$0/ emulationにあるときにスクリプト名を保持します(anon)set +o functionargzeroshksh

zshように、cshスクリプトの引数は配列にあるため、引数の命名に似$argvたプログラム名は複雑になりません。

ここでは、次を使用して位置パラメータに値を割り当てることができます。

argv[1]=value

または

1=value

0=newprogramnameプログラム名を変更することもできます)。

Bourneなどの他のシェルでは、すべてを一度に割り当てる必要がありますset

set -- arg1 arg2

そして、あなたはそれを変更することはできません$0

rc(少なくともパブリックドメインレプリケーションでは)次のことはできません。

1 = value

しかし、次のようにすることができます。

* = (arg1 arg2)

位置パラメータを設定します。$0では変更できませんが、like inを使用して派生を変更rcできます。es0=newprogramnamezsh

長い話を短く

, $1... $2Thompson シェルから出るが呼び出されないスクリプト引数を表します。位置パラメータしかし。そして$0(おそらく@ikkachuが言ったことに関してargv[0])スクリプト名を表します。

これ位置パラメータこの用語はBourne Shellに由来しています。

$0スクリプトのパラメータを参照していないため、位置パラメータではありません。これはスクリプトの名前を表します(argv[0]シェルがスクリプトを実行していない場合はシェルの名前を表します。一部のシェルでは、関数内で使用した場合の関数の名前を表します)。

答え2

番号付きパラメータ($0、、、$1...)argv[]は、プロセスの開始時にコマンドラインパラメータを含む配列と明らかに似ています。配列の最初の要素は通常argv[0]プロセスの名前を持ち、実際のパラメータはそこから始まりますargv[1]

(普通。必ずしもそうではありません。execve(2)状態説明:「値はargv[0] しなければならない起動するプロセスに関連するファイル名文字列へのポインタ")

少なくとも振り返ってみると、このルールが単にシェルに直接コピーされたことを想像するのは簡単です。

ただし、これらの値は直接コピーされません。少なくとも私のシステムでは、 ./script.shhashbangの実行時に開始されたシェルプロセスを使用して#!/bin/bash -xパラメータ/bin/bash、、、-xを取得します./script.sh。つまり、$0スクリプトで表示される値はargv[2]シェルプロセスにあります。

私はほとんどの人がコマンド名を引数とは別に考えると仮定します$0機能的に他人と違うので違うように呼んでも無理はありません。

もちろん、異なる命名規則を使用するスクリプト言語を使用することもできます。 Perlは、プログラム名を名前付き変数に入れ、引数をインデックス0から始まる$0配列に入れます。@ARGV$ARGV[0]


とにかく最も明確な答えは、これが$0位置パラメータではないということです。標準にそう出ているから:

下に2.5 パラメータと変数

2.5.1 位置パラメータ

位置パラメーターは、1 つ以上の数値 (1 桁の 0 を除く) で表される 10 進値で表されるパラメーターです。

2.5.2 特殊パラメータ

# 位置引数の10進数に拡張します。コマンド名(引数0)は#位置引数ではなく特殊引数であるため、 ""で指定された数字に含めないでください。

0 (0.) シェルまたはシェルスクリプトの名前に展開されます。

答え3

$ 0は実際には位置引数です(以下のMichael Homerの説明で指摘したように、POSIXは "...引数名を1からnまでの番号付き位置引数として取り、コマンド名(または関数の場合)を使用します。スクリプトではスクリプト名前)位置パラメータ番号が0の場合」。

予想されるように、これは呼び出しコマンドの名前を表す位置0のパラメーターです。

これは、同じスクリプトが呼び出し名によって異なる動作をすることを可能にし、同じ実行可能ファイルが複数の機能(たとえば、シンボリックリンクなど)を持つことを可能にするので便利です。これにより、プロセスは呼び出し名が何であるかを知ることができます。

/ binを少し見てみると、bzcat、bzcmp、bzip2、...、mdir、mcat、mcd、mdel、...などの多くの例が表示されます。 。プロセスが実行する機能を知る方法は、位置パラメータ0を確認することです。

注:一部のシェルのマニュアルページでは、用語を異なる方法で扱うことができます。 bashのマニュアルページでは位置パラメータではないと言い、kshのマニュアルページ(およびPOSIX定義)ではそうです。用語の議論に関係なく、(bashとksh)$ 0には呼び出しコマンドまたはスクリプトの名前が含まれています。対話型シェルの場合、$ 0はプロセス名であるため、シェル名(bash、ksh ...)が含まれます。

関連情報