$0이 위치 매개변수가 아닌 이유는 무엇입니까?

$0이 위치 매개변수가 아닌 이유는 무엇입니까?

위치 매개변수가 시작된다는 내용을 읽었습니다 $1(예: $1, $2등은 $3위치 매개변수입니다). 그러나 $0위치 매개변수는 아닙니다.

그런데 왜 $0위치 매개변수가 아닌가?

이것이 이유일 수도 있지만 확실하지는 않습니다.

위치 매개변수는 스크립트가 실행될 때만 해당 값을 갖습니다. 예를 들어 ./myScript Hello, 이렇게 하면 $1가치가 있을 것입니다 Hello. 그러나 $0그 값은 스크립트가 실행될 때(스크립트 이름의 값을 갖게 됨)와 bash스크립트 없이 자체가 실행될 때( bash또는 값을 갖게 됨 -bash)의 두 가지 경우에 얻을 수 있습니다.

답변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이 필요한 이유를 설명합니다( 역방향 이식성 ) . 10번째).$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 위치 매개변수

위치 매개변수는 하나 이상의 숫자(한 자리 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...)이 포함됩니다.

관련 정보