이전 명령의 마지막 인수는 무엇입니까?


12

$_ 이전 명령의 마지막 인수라고합니다.

나는 그것이없는 이유를 궁금해 그래서 EDITOR="emacs -nw"하지만 EDITOR다음 예에?

"emacs -nw"마지막 논쟁의 일부 가 아닌 이유는 무엇 입니까?

더 일반적으로, 인수의 정의와 마지막 인수는 무엇입니까?

감사.

$ export EDITOR="emacs -nw"
$ echo $_
EDITOR

3
쉘 체크가 변수를 할당 한 줄과 같은 줄에 내 보내지 말라고 알려주는 것과 같은 이유로 생각합니다. 할당이 수행 된 후 변수가 내보내집니다. EDITOR수출에 대한 논쟁
jesse_b

FWIW는, pdkshdash할당 된 값을 포함하지만 ksh93로 작동합니다 bash않습니다.
Kusalananda

zsh : export FOO=bar; echo $_인쇄합니다 export.
ilkkachu

@Jesse_b 모든 것은 마지막 인수 / 피연산자 (할당 된 값 포함)이지만 export내장 유틸리티 라는 사실과 관련이있을 수 있습니다 .
Kusalananda

ksh : typeset -x FOO=bar다음에 echo $_인쇄 FOO하지만 Bash에서 declare -x FOO=bar; echo $_인쇄합니다 FOO=bar.
ilkkachu

답변:


13

배쉬 (과 그들이 인수로 사용할 때, 변수 할당을 처리 alias, declare, export, local, readonly,과 typeset) 다른 어떤 전에 (- 확장 변수에 할당 된 값에 적용 또는 오히려, 그것은 아무것도하기 전에 식별). 이 단어 확장에 도달하면, 나머지 명령이있다 export EDITOR, 그래서 _으로 설정됩니다 EDITOR.

일반적으로 인수는 확장 후 남은 "단어"입니다 (변수 할당 및 방향 재 지정은 포함되지 않음).

자세한 내용 은 Bash 매뉴얼의 간단한 명령 확장 을 참조하십시오.


그리고 나는 declare행동이 내가 묘사 한 것과 일치하지 않는다는 것을 알고 있습니다 .
Stephen Kitt

글쎄요, 그것은 그다지 일관성이 없습니다. declare a=b; echo $_인쇄 a=b; export c=d; echo $_그냥 인쇄합니다 c. 반면에 alias이름 만 인쇄하는 것처럼 보이지만 local전체 인수를 인쇄합니다. 또한 readonly이름 만 인쇄 합니다 . 생각 readonlylocal생각이 비슷하기 때문에 조금 놀랍 습니다 declare.
ilkkachu

1
@ ilkkachu heh, 나도 그것을 깨달았다 (위 참조). exportreadonly함께 선언 setattr.def, declare, local,과 typeset에 선언 declare.def, alias혼자 서있다 alias.def.
Stephen Kitt

감사. 변수 할당이 일부 명령에 대한 인수로 사용될 때 (1) "(또는 변수가 변수에 할당 된 값에 적용되는 다른 것보다 먼저 변수를 식별합니다") 변수 할당을 수행하기 전에 값에 확장이 발생한다는 의미입니까? (2) "단어 확장에 도달하면 나머지 명령은 내보내기 EDITOR"입니다. 확장하기 전에 변수 할당을 수행하는 것을 의미합니까? 두 따옴표는 서로 모순되는 것 같습니다.
Tim

감사. 조금 혼란 스러워요. 변수 할당은 인수에 사용하는 경우 alias, declare, export, local, readonlytypeset. 처음과 다음에 어떤 일이 발생합니까? "단어 확장에 도달하면 나머지 명령은 export EDITOR"입니다. EDITOR="emacs -nw"확장 전에 변수 할당이 발생 했음을 의미 합니까? 그렇지 않은 경우 나머지 명령에 할당이 인수로 포함되지 않은 이유는 무엇입니까? 그렇다면 변수 할당을 수행하기 전에 변수에 지정된 값을 확장하지 않아도됩니까?
Tim

4

TL; DR :의 경우 export FOO=bar, bash는 임시 환경 작성을 호출하고 FOO=bar해당 환경을 설정 한 다음 최종 명령을 생성합니다 export FOO. 이때 FOO마지막 인수로 간주됩니다.


아, 많이 욕설 $_:

($ _, 밑줄) 쉘 시작시 환경 또는 인수 목록에 전달 된대로 실행중인 쉘 또는 쉘 스크립트를 호출하는 데 사용되는 절대 경로 이름으로 설정하십시오. 결과적으로 확장 후 이전 명령의 마지막 인수로 확장됩니다. 또한 실행되어 해당 명령으로 내 보낸 환경에 배치 된 각 명령을 호출하는 데 사용되는 전체 경로 이름으로 설정하십시오. 메일을 확인할 때이 매개 변수는 메일 파일의 이름을 보유합니다.

몇 가지 변형을 살펴 보겠습니다.

$ man; echo $_
What manual page do you want?
man
$ man foo; echo $_
No manual entry for foo
foo
$ echo; echo $_

echo
$ echo bar foo; echo $_
bar foo
foo
$ foo=x eval 'echo $foo'; echo $_
x
echo $foo
$ bar() { man $1; }; echo $_
foo
$ for (( i=0; $i<0; i=i+1 )); do echo $i; done; echo $_
foo
$ bar; echo $_
What manual page do you want?
man
$ bar foo; echo $_
No manual entry for foo
foo
$ MANPATH=/tmp; echo $_

$ export MANPATH=/tmp; echo $_
MANPATH

여기에 세 가지 패턴이 있습니다.

  • 파일 시스템, 함수 및 내장에서 호출 된 명령은 일반적으로 예상 한대로 작동합니다. $_인수가 없으면 명령 이름 자체로 설정되고, 그렇지 않으면 마지막으로 제시된 인수가 설정됩니다.
  • 함수 정의, 루프 및 기타 논리적 구성 후에 $_는 수정되지 않습니다.
  • 그 밖의 모든 것 : $_예상치 못한 것으로 설정되었습니다. 기묘한.

이상한 점에 대한 통찰력을 제공하기 위해 코드를 계측했습니다.

$ ./bash --noprofile --norc -c 'man foo'
lastword=[man]
lastarg=[foo]
$ ./bash --noprofile --norc -c 'export FOO=bar'
lastword=[export]
lastarg=[FOO=bar]
bind_variable, name=[FOO], value=[bar]
before bind_lastarg, lastarg=[FOO]
bind_lastarg, arg=[FOO]
bind_variable, name=[_], value=[FOO]
$ ./bash --noprofile --norc -c 'declare FOO=bar'
lastword=[declare]
lastarg=[FOO=bar]
bind_variable, name=[FOO], value=[(null)]
before bind_lastarg, lastarg=[FOO=bar]
bind_lastarg, arg=[FOO=bar]
bind_variable, name=[_], value=[FOO=bar]

파서lastarg=모든 경우에 예상되는 마지막 인수 ( )를 볼 수 있지만 그 이후에 발생하는 일은 bash가 어떻게 생각 해야하는지에 달려 있습니다. execute_cmd.c, execute_simple_command ()를 참조하십시오 .

의 경우 export FOO=barbash는 할당을 한 다음 변수를 내 보냅니다. 이것은 확장 후 마지막 인수가 계산 된 문서의 주장과 일치하는 것 같습니다.


1
쉘이 메일을 확인하고 있다는 것을 어떻게 알 수 있습니까?
rackandboneman

@rackandboneman, 확인하지 않고 내부 점검을 수행 한 것으로 의심됩니다.MAILCHECK
Jeff Schaller

2

제목 질문에 대답하려면 다음을 시도하십시오 !$.

$ export EDITOR="emacs -nw"
$ echo !$
EDITOR=emacs -nw

이것은 역사 확장입니다. bash 맨 페이지에서 :

기록 확장은 완전한 행을 읽은 직후에 쉘이 단어로 나누기 전에 수행됩니다. 두 부분으로 이루어집니다. 첫 번째는 히스토리 목록에서 대체 중에 사용할 행을 결정하는 것입니다. 두 번째는 현재 라인에 포함 할 라인의 일부를 선택하는 것입니다. 히스토리에서 선택한 라인은 이벤트이며 해당 라인의 일부는 단어입니다.

...

이벤트 지정자

...

! 공백, 개행, 캐리지 리턴, = 또는 뒤에 오는 경우를 제외하고 히스토리 대체를 시작하십시오 (extglob 쉘 옵션이 shopt 내장을 사용하여 활성화 된 경우).

...

!! 이전 명령을 참조하십시오. 이것은`! -1 '의 동의어입니다.

...

단어 지정자

...

$ 마지막 단어. 이것은 일반적으로 마지막 인수이지만 줄에 단어가 하나만 있으면 0 번째 단어로 확장됩니다.

...

이벤트 지정없이 단어 지정자가 제공되면 이전 명령이 이벤트로 사용됩니다.


당신은 문자 그대로 질문의 제목을 취하고 있습니다. (좋아요, 제목이 좋지 않습니다.) 우리는« export EDITOR="emacs -nw"» 명령 이 두 단어로 구성되어 있음을 알 수 있습니다. 첫 번째는« export»이고 두 번째는« EDITOR="emacs -nw"»입니다. 문제는 "배쉬 매뉴얼 페이지와 Bash 매뉴얼은 !_bash $_가« EDITOR»로 설정 되어 있다면 '이전 명령의 마지막 인수로 확장된다' 고 말할 때 무엇을 의미 하는가?"입니다. 히스토리 확장에 대한 bash 매뉴얼 페이지 섹션을 복사하여 붙여 넣는 것은 특별히 도움이되지 않습니다.
G-Man, 'Reinstate
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.