$ 0 및 $ 1 쉘 / 환경 변수와 같은 변수가 있습니까?


17

같은 쉘의 변수가있다 $0, $1, $2, $?, 등

다음 명령을 사용하여 쉘 및 환경 변수를 인쇄하려고했습니다.

set

그러나 이러한 변수는 목록에 없었습니다.

기본적으로 이러한 변수는 쉘 / 환경 변수로 간주되지 않습니다. (출력을하더라도 $쉘 / 환경 변수와 같이 앞에을 붙여야합니다 )


3
위치 매개 변수는 변수가 아닙니다. 환경 변수 export 3로 전환 할 수 없습니다 $3. 당신은 할 수 없습니다 unset 3; 를 $3사용하여 새 값을 할당 할 수 없습니다 3=val.
Kaz

답변:


25

변수는 쉘에서 세 가지 다른 변수 중 하나입니다.

  1. 변수 이름이 유효한 셀 식별자 파라미터이고; 시작 _또는 0 개 이상의 문자, 숫자 또는 다음 편지, _.
  2. 위치 파라미터는 파라미터이다 번째 $1, $2...
  3. 특별한 매개 변수는 모든 단일 문자 이름을 가지고 있고, 옆에서 $0, 그들은 모두 다양한 문장 부호입니다.

set 쉘 변수 만 표시합니다.

쉘 변수의 서브 세트는 환경 변수로, 쉘이 시작될 때 환경에서 값이 상속되거나 export유효한 이름으로 속성을 설정하여 작성됩니다 .


1
참고 set표시의 모든 매개 변수 zsh(하지 $ 1, $ ... 2 만 $ *, $ @)와 떠들썩한 파티와 보쉬의 기능을합니다. ksh93과 같은 일부 쉘 및 쉘 변수에 맵핑되지 않은 이전 버전의 대시 출력 env vars. ( env 1=foo ksh -c set인쇄 것 1=foo)
스테판 Chazelas가에게

11

환경 변수와 위치 매개 변수

$INTEGER변수 유형에 대해 논의하기 전에 변수가 실제로 무엇이고 환경 변수와 어떻게 다른지 이해해야합니다 $INTEGER. 이것은 POSIX (Portable Operating System Interface) 표준, 섹션 2.1 (강조 광산)에 설명되어 있습니다.

  1. 쉘은 함수 (함수 정의 명령 참조), 내장 (특수 내장 유틸리티 참조), 실행 파일 또는 스크립트를 실행 하여 인수의 이름을 1-n까지의 위치 매개 변수로 지정하고 명령 이름을 제공합니다. (또는 스크립트 내의 함수 인 경우 스크립트 이름)는 위치 매개 변수 번호가 0입니다 (명령 검색 및 실행 참조).

이와는 대조적으로, 같은 변수 $HOME$PATH환경 변수이다. 그들의 정의는 표준의 섹션 8에 설명되어 있습니다 .

이 장에서 정의 된 환경 변수는 여러 유틸리티, 기능 및 응용 프로그램의 작동에 영향을줍니다. 특정 유틸리티에만 관심이있는 다른 환경 변수가 있습니다. 단일 유틸리티에만 적용되는 환경 변수는 유틸리티 설명의 일부로 정의됩니다.

그들의 설명을 주목하십시오. 위치 매개 변수는 명령 앞에 나타납니다 (예 :) command positional_arg_1 positional_arg_2.... 명령은 사용자가 구체적으로해야 할 일을 알려주기 위해 제공됩니다. 당신이 할 때 echo 'Hello' 'World', Hello그리고 당신이 작업하고자하는 것들에 대한 World위치 매개 변수이기 때문에 및 문자열을 인쇄 합니다. 그리고 위치 매개 변수를 인쇄 할 문자열로 이해하도록 작성되었습니다 (이와 같은 선택적 플래그 중 하나가 아닌 한 ). 당신이 다른 명령으로이 작업을 수행 할 경우 이해하지 않을 수 있습니다 무엇을 하고echoechoecho-nHelloWorld아마도 숫자를 기대하기 때문입니다. 위치 매개 변수는 "상속"되지 않습니다. 자식 프로세스는 자식 프로세스에 명시 적으로 전달되지 않는 한 부모의 위치 매개 변수에 대해 알지 못합니다. 종종 래퍼 스크립트와 함께 위치 매개 변수가 전달되는 것을 볼 수 있습니다. 이미 존재하는 명령 인스턴스를 확인하거나 호출 될 실제 명령에 추가 위치 매개 변수를 추가 할 수 있습니다.

반대로 환경 변수는 여러 프로그램에 영향을 미칩니다. 그것들은 프로그램 자체 밖에서 설정되기 때문에 환경 변수입니다 (자세한 내용은 아래 참조). 같은 특정 환경 변수 HOME또는 PATH특정 형식, 특별한 의미를 가지고 있고, 그들은 각 프로그램에 동일한 의미하는 것이다. HOME변수는 외부 /usr/bin/find쉘이나 쉘 과 같은 외부 유틸리티와 같 으며 (따라서 스크립트와 동일) 프로세스가 실행되는 사용자 이름의 홈 디렉토리입니다. 예를 들어 환경 변수를 사용하여 특정 명령 동작을 설명 할 수 있습니다.UID환경 변수를 사용하여 스크립트가 루트 권한으로 실행되는지 여부를 확인하고 그에 따라 특정 작업으로 분기 할 수 있습니다. 환경 변수는 상속 가능합니다. 자식 프로세스는 부모 환경의 복사본을 얻습니다. 참조 프로세스가 부모의 환경을 상속하는 경우, 왜 우리가 수출해야합니까?

간단히 말해서, 주요 차이점은 환경 변수가 명령 외부에 설정되어 있으며 (대개) 변경되지 않는 반면, 위치 매개 변수는 명령에 의해 처리되고 변경되는 것입니다.


쉘 개념뿐만 아니라

내가 의견에서 주목 한 것은 터미널과 셸을 혼합하고 있으며 한때 물리적 장치였던 실제 터미널 에 대해 읽는 것이 좋습니다 . 오늘날 우리가 일반적으로 언급하는 "터미널"은 검은 색 배경과 녹색 텍스트가있는 창은 실제로 소프트웨어이며 프로세스입니다. 터미널은 쉘을 실행하는 프로그램이지만 쉘은 프로그램이지만 실행하기 위해 입력 한 내용을 읽는 프로그램입니다 (즉, 대화식 쉘인 경우 비 대화식 쉘은 스크립트 및 sh -c 'echo foo'호출 유형 임). 포탄에 대한 자세한 내용은 여기를 참조하십시오 .

이것은 중요한 차이점이지만 터미널이 프로그램임을 인식하고 동일한 환경 규칙 및 위치 매개 변수를 준수해야합니다. 당신의 gnome-terminal당신 볼 것이다 시작된 SHELL환경 변수, 당신은 몇 가지 다른 명령을 지정하지 않는 한, 당신을 위해 적절한 기본 쉘을 산란 -e. 기본 쉘을 ksh -gnome-terminal 로 바꾸고 ksh대신에 스폰 한다고 가정 해 봅시다 bash. 그것은 또한 프로그램이 환경을 사용하는 방법의 예입니다. 내가 명시 적으로 말할 경우 gnome-terminal-e특정 쉘을 실행 - 그것은 그것을 할 것입니다,하지만 영구적으로하지 않습니다. 대조적으로, 환경은 대부분 변경되지 않아야합니다 (나중에 자세히 설명).

보시다시피, 환경 및 위치 변수는 모두 쉘이 아닌 프로세스 / 명령의 속성입니다. 쉘 스크립트는 C 프로그래밍 언어로 설정된 모델을 따릅니다. 예를 들어 main일반적으로 보이는 C 함수 를 예로 들어 보겠습니다.

int main(int argc, char **argv)

(여기서 argc명령 줄 인수의 수이며, argv효과적으로 명령 줄 매개 변수의 배열이며, 사용자의 홈 디렉토리 경로, 실행 파일을 찾을 수있는 디렉토리 목록 등과 같은 항목에 액세스 environ하는 기능 (Linux의 경우 man -e 7 environ)이 있습니다 PATH. 쉘 스크립트도 비슷한 방식으로 모델링됩니다. 쉘 용어에는 위치 매개 변수 $1등이 $2있으며, $#여러 위치 매개 변수가 있습니다. 무엇에 대해 $0? 그것은 C 프로그램 언어에서 다시 모델링 된 실행 파일 자체의 argv[0]이름입니다. C "실행 파일"의 이름이됩니다. 그리고 이것은 대부분의 프로그래밍 및 스크립팅 언어에있어 상당히 사실입니다 .

대화식 대 비 대화식 쉘

내가 이미 암시 한 것 중 하나는 대화식 쉘과 비 대화식 쉘 의 차이점 입니다. 명령을 입력하는 프롬프트-대화식이며 사용자와 상호 작용합니다. 반대로 쉘 스크립트가 있거나 bash -c''비 대화식으로 실행할 때.

그리고 이것이 구별이 중요 해지는 곳입니다. 이미 실행하는 것이 쉘에 대한 위치 매개 변수 (로 양산 된 과정입니다 bash(- "., 또는 --login 옵션으로 시작 하나 ... 그 첫 번째 문자 인수가 제로이다"로그인 쉘 하나입니다 참조 ) )

반면, 스크립트와 쉘과 시작 -c의 장점이 걸릴 수 있습니다 옵션 $1$2인수를. 예를 들어

$ bash -c 'echo $1; stat $2' sh 'Hello World' /etc/passwd
Hello World
  File: '/etc/passwd'
  Size: 2913        Blocks: 8          IO Block: 4096   regular file
Device: 801h/2049d  Inode: 6035604     Links: 1
Access: (0644/-rw-r--r--)  Uid: (    0/    root)   Gid: (    0/    root)
Access: 2017-08-12 14:48:37.125879962 -0600
Modify: 2017-08-12 14:48:37.125879962 -0600
Change: 2017-08-12 14:48:37.137879811 -0600
 Birth: -

옵션의 sh작은 단점은 일반적으로 프로그램의 이름과 달리 -c첫 번째 위치 매개 변수를 가져 와서 할당하는 것이므로 여기에서도 사용 했습니다 $0.

주목해야 할 또 다른 사항은 위치 매개 변수가 내가 "프레임 가능"이라고하는 것입니다. 처음에 bash자체 위치 매개 변수로 시작했지만 이러한 위치 매개 변수가 echo및의 매개 변수가 된 방법에 주목하십시오 stat. 그리고 각 프로그램은 고유 한 방식으로 이해합니다. stat문자열 을 주었고 Hello World파일 Hello World이 없으면 오류가 발생합니다. bash간단한 문자열로 취급하지만 stat해당 문자열이 기존 파일 이름이 될 것으로 예상합니다. 반대로, 모든 프로그램은 환경 변수 HOME가 디렉토리 라는 것에 동의합니다 (프로그래머가 불합리한 방식으로 코딩하지 않는 한).


환경 변수와 위치 매개 변수를 혼동시킬 수 있습니까?

기술적으로 우리는 둘 다 엉망이지만 환경 변수를 엉망으로 만들지 말고 위치 매개 변수를 제공해야합니다. 다음과 같이 변수를 앞에 추가하여 셸에서 명령을 실행할 수 있습니다.

$ hello=world bash -c 'echo $hello'
world

export variable=value쉘이나 스크립트 내에서 간단히 사용하여 변수를 환경에 배치 할 수도 있습니다 . 또는로 완전히 빈 환경에서 명령을 실행할 수 있습니다 env -c command arg1 arg2. 그러나 일반적으로 환경, 특히 대문자 변수를 사용하거나 기존 환경 변수를 덮어 쓰는 것은 바람직하지 않습니다. 표준은 아니지만 권장됩니다.

위치 매개 변수의 경우 매개 변수를 설정하는 방법은 분명합니다. 명령 앞에 추가하면되지만 다른 현명 하게 설정하고shift 명령을 통해 해당 매개 변수 목록을 변경하는 방법도 있습니다 .

결론적으로이 두 가지의 목적은 다르며 이유가 있습니다. 사람들이이 답변으로부터 통찰력을 얻었기를 바랍니다.이 답변을 쓰는 ​​것과 마찬가지로 그것을 읽는 것이 재미있었습니다.


set 명령에 대한 참고 사항

set명령과 같이 행동한다 설명서에 따라 (배시 교재 강조 첨가)

옵션이 없으면 각 쉘 변수 의 이름과 값이 현재 설정된 변수를 설정하거나 재설정하기위한 입력으로 재사용 할 수있는 형식으로 표시됩니다.

다시 말해 set, 쉘과 관련된 변수를 살펴보면, 일부는 환경에 있습니다 (예 :) HOME. 대비와 같은 명령에 의해 envprintenv실제 환경 변수와 명령이 실행 봐. 참조 .


"대화식 쉘에서는 $ 1, $ 2 등을 참조 할 수 없습니다."이에 대한 직접적인 참조가 있습니까? 대화 형 셸 환경에서 설정되는 이상한 경우가 발생했으며 이것이 '비표준'으로 간주되는지 여부는 확실하지 않습니다.
user5359531

@ user5359531 솔직히, 나는 그것이 어디서 왔는지 확실하지 않습니다. 아마도 2017 년에 답을 게시했을 때 아마도 당신이 같은 것을 할 수 없다는 것을 언급 1="foo"했지만 나중에 POSIX 정의에 의해 "word"(변수 또는 함수와 같은 객체의 이름)가 시작할 수 없다는 것을 알았습니다. 숫자와 함께 ( 주제에 게시질문 참조 ). 위치 매개 변수는 분명히이 규칙에서 예외입니다.
Sergiy Kolodyazhnyy

@ user5359531 특히 정확하지 않기 때문에 답변의 일부를 제거했습니다. 대화식 쉘에서 참조 $1등을 할 수 $2있으며 실제로는 배열이 없다는 제한을 set피하기 위해 명령으로 수행됩니다 /bin/sh. 관심을 가져 주셔서 감사합니다. 또한 약간의 추가 개선과 업데이트가 필요하므로 향후 며칠 동안 답변을 편집 할 것입니다.
Sergiy Kolodyazhnyy

설명해 주셔서 감사합니다. 내가 데 문제가 함께 있다는 것입니다 conda실행할 때, source conda/bin/activate여부에 그것을 검사 $1, $2등, 그것은 인수 여부와 스크립트로 실행 된 여부를 결정하기 위해 설정된다. 이것은 어떤 이유로 대화 형 환경에서 설정된 시스템을 중단시킵니다. 이 비표준 동작이 대화 형 환경에서 이러한 변수를 설정하는 시스템의 결함인지 또는 스크립트로 실행되었는지 확인하기 위해 프로그램에서 사용하는 결함인지 확인하고 싶습니다.
user5359531

@ user5359531 매개 변수 conda를 확인하는 ${N}것은 확실히 잘못된 방법이므로 개발자 또는 스크립트 작성자 인 사람 에게 버그 보고서를 제출하는 것이 좋습니다 . 여기여기에 같은 주제에 대한 질문이 있으며 , 다소 이식성이 좋은 방법은 ${0}스크립트 이름과 같은지 확인하는 것 입니다. bash실제로 그 목적에 맞는 환경 변수가 있습니다
Sergiy Kolodyazhnyy

4

$1, $2, $3, ..., ${10}, ${11}변수 위치 매개 변수라고하며 떠들썩한 파티 매뉴얼 섹션에서 다루는3.4.1

3.4.1 위치 매개 변수

위치 매개 변수는 단일 숫자 0 이외의 하나 이상의 숫자로 표시되는 매개 변수입니다. 위치 매개 변수는 호출 될 때 쉘의 인수에서 지정되며 set builtin 명령을 사용하여 다시 지정할 수 있습니다. 위치 매개 변수 N은 $ {N} 또는 N이 한 자리로 구성되는 경우 $ N으로 참조 될 수 있습니다. 할당 문에는 위치 매개 변수를 할당 할 수 없습니다. set 및 shift 내장은 설정 및 설정 해제에 사용됩니다 (Shell 내장 명령 참조). 쉘 기능이 실행될 때 위치 매개 변수가 일시적으로 대체됩니다 (쉘 기능 참조).

두 자리 이상의 숫자로 구성된 위치 매개 변수가 확장되면 중괄호로 묶어야합니다.

에 관해서 $?$0,이 특별한 매개 변수는 바로 다음 섹션에 설명되어 있습니다3.4.2

3.4.2 특수 매개 변수

쉘은 여러 매개 변수를 특별히 처리합니다. 이 매개 변수는 참조 만 가능합니다. 그들에게 할당은 허용되지 않습니다.

...

?

($?) 가장 최근에 실행 된 포 그라운드 파이프 라인의 종료 상태로 확장됩니다.

0

($ 0) 쉘 또는 쉘 스크립트 이름으로 확장합니다. 이것은 셸 초기화시 설정됩니다. 명령 파일 (Bash 스크립트 참조)로 Bash를 호출하면 $ 0이 해당 파일 이름으로 설정됩니다. Bash가 -c 옵션으로 시작되면 (Bash 호출 참조) $ 0은 실행될 문자열 뒤의 첫 번째 인수 (있는 경우)로 설정됩니다. 그렇지 않으면 인수 0으로 지정된대로 Bash를 호출하는 데 사용 된 파일 이름으로 설정됩니다.


4

$1, $2... 위치 매개 변수이며, 환경 변수는 물론 변수가 아닙니다.

본쉘 같은 용어에서 $something라고 매개 변수 확장 (또한 커버 ${something#pattern}등과 같은 몇 가지 껍질에 ${array[x]}, ${param:offset}, ${x:|y}그리고 더 많은 확장 사업자).

여러 종류의 매개 변수가 있습니다.

  • 변수는 좋아 $foo,$PATH
  • 위치 매개 변수 ( $1, $2... 스크립트가 수신 한 인수)
  • 기타 특수 매개 변수이 좋아 $0, $-, $#, $*, $@, $$, $!, $?...

Bourne의 쉘과 같은 변수 이름은 하나의 알파벳 문자 (로케일에 의해 인식되거나 쉘에 따라 a-zA-Z로 제한됨)와 밑줄로 시작하고 0 개 이상의 영숫자 문자 또는 밑줄로 시작해야합니다.

쉘에 따라 변수는 다른 유형 (스칼라, 배열, 해시)을 갖거나 특정 속성 (읽기 전용, 내 보낸, 소문자 ...)을 가질 수 있습니다.

이러한 변수 중 일부는 쉘에 의해 생성되거나 쉘에 특별한 의미를 갖습니다 (예 $OPTIND: $IFS,, $_...)

내보내기 속성이 있는 쉘 변수는 환경 변수 로 쉘이 실행하는 명령에 자동으로 내보내집니다 .

환경 변수는 쉘 변수와 분리 된 개념입니다. 환경 변수를 명령 실행에 전달하는 유일한 방법은 쉘 변수를 내보내는 것이 아닙니다.

VAR=foo
export VAR
printenv VAR

VAR환경 변수를 printenv명령에 전달합니다 (내용을 인쇄하도록 지시합니다).

env VAR=foo printenv VAR

또는:

perl -e '$ENV{VAR}="foo"; exec "printenv", "VAR"'

예를 들어.

환경 변수는 임의의 이름을 가질 수 있습니다 (모든 문자를 포함 =할 수 있지만 비어있을 수도 있음). Bourne과 같은 쉘 변수 이름과 호환되지 않는 이름을 환경 변수에 제공하는 것은 좋지 않지만 가능합니다.

$ env '#+%=whatever' printenv '#+%'
whatever

쉘은 이름이 유효한 쉘 변수 인 환경 변수에 대해서만 수신 한 환경 변수 를 쉘 변수에 맵핑합니다 (일부 쉘에서는와 같은 일부 특수 변수는 무시합니다 $IFS).

따라서 1환경 변수를 명령 에 전달할 수는 있지만

$ env '1=whatever' printenv 1
whatever

그렇다고 해당 환경 변수로 쉘을 호출하면 $1매개 변수 의 값이 설정된다는 의미는 아닙니다 .

$ env '1=whatever' sh -c 'echo "$1"' script-name foo bar
foo

3

아니요, 스크립트의 매개 변수입니다. 예를 들어 다음과 같이 스크립트를 호출하면

mynicescript.sh one two three

그런 다음 스크립트 내부에서 이러한 매개 변수를 사용할 수 있습니다

$1 = one
$2 = two
$3 = three

$ 0는 스크립트 자체의 이름입니다.

따라서 스크립트 외부에 있으면 이러한 변수를 사용할 수 없습니다 ($ 0 제외, / bin / bash-셸 자체).


"따라서 스크립트 외부에있을 때는 이러한 변수를 사용할 수 없습니다" 터미널에서 이러한 변수의 값을 볼 수 있기 때문에 "스크립트 외부 "는 무엇을 의미합니까?
user7681202

2
@ user7681202 : 터미널에서 어떤 것을 볼 수 있습니까? $0현재 터미널 프로세스 (bash와 유사)를 가리키며 $?단순히 마지막 프로세스의 종료 코드입니다.
Jesse_b

gnome-terminalwith 인수 ( gnome-terminal Hello World) 를 실행하려고했습니다 . 나는 볼 수 있었다 $0, 그러나 나는 볼 수 없었다 $1$2.
user7681202

@Jesse_b 감사합니다. $ 0의 내용을 답변에 추가했습니다.
Jaroslav Kucera

1
@ user7681202 gnome-terminal은 쉘이 아니며 터미널 에뮬레이터입니다 (xterm, konsole 등). 쉘은 터미널 내부에서 실행되며 bash / sh / zsh / tcsh 등이 될 수 있습니다. 스크립트는 적절한 헤더 (예 : #! / bin / bash)와 마스크에 지정된 셸에서 해석 할 수있는 내용이있는 실행 파일입니다. 그것은 일반적으로 접미사의 .sh를 사용
야로슬라프 쿠 세라에게
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.