위치 매개 변수가있는 Bash -c


15

일반적으로 $0스크립트에서 스크립트 이름 또는 호출 된 모든 경로 (경로 포함)로 설정됩니다. 그러나 옵션 bash과 함께 사용 하면 명령 문자열 다음에 전달되는 첫 번째 인수로 설정됩니다.-c$0

bash -c 'echo $0 ' foo bar 
# foo 

실제로 위치 매개 변수가 이동 된 것처럼 보이지만을 포함 $0합니다. 그러나 shift명령 문자열에서 $0(정상적으로) 영향을 미치지 않습니다 .

bash -c 'echo $0; shift; echo $0 ' foo bar
# foo
# foo

왜 명령 문자열에 대해 이상한 행동입니까? 나는 그런 이상한 행동을 구현 한 이유, 이유를 찾고 있습니다.


그러한 명령 문자열 $0에는 일반적으로 정의 된대로 매개 변수 가 필요하지 않다고 추측 할 수 있으므로 경제성을 위해 일반 인수에도 사용됩니다. 그러나이 경우 동작 shift이 이상합니다. 또 다른 가능성은 $0프로그램의 동작을 정의하는 데 사용되는 (la bash라고 sh또는 vim호출이라고 함 vi) $0여기서는 명령 문자열에서만 볼 수 있으며 프로그램 내에서 호출 된 프로그램에서는 볼 수 없기 때문입니다. 에 대한 다른 용도를 생각할 수 없으므로 이에 대해 설명하지 못했습니다 $0.


보조 노트로서, 나는의 사용 보았다 -에 대한 $0처럼 관용구 등의 인수를 sh -c 'foo $1 $2' - a b. 이 방법은 꽤 평범 해 보입니다 (한 번 -의미 하는 것을 알게되면 )
Volker Siegel

당신은 또한 수 있습니다 echo 'echo the other side of this pipe globs "$@"' | sh -s -- *,하지만, 불행하게도, $0일반적으로 설정 가능한 매개 변수없는 -stream 옵션 ... 같은 방법으로 많은 사용할 수 있습니다 xargs일반적으로 생각입니다. 그리고 다른 사람.
mikeserv

@VolkerSiegel 좀 더 평범했을 것입니다 --. 그러면 다른 프로그램에서 볼 수 있듯이 '여기부터 인수를 시작합니다'라는 일반적인 해석이 있었을 것입니다. 그리고 다시, 그것은 실제로 그 해석을 가지고 -c있다고 생각 하는 것에 익숙하지 않은 사람들을 혼동 할 수 있습니다 --.
muru

답변:


10

$0따라서 인라인 스크립트를 사용할 때 설정 / 선택할 수 있습니다 . 그렇지 않으면 $0그냥 있습니다 bash.

그런 다음 예를 들어 할 수 있습니다.

$ bash -c 'wc -c < "${1?}"' getlength foo
4
$ bash -c 'wc -c < "${1?}"' getlength bar
getlength: bar: No such file or directory
$ bash -c 'wc -c < "${1?}"' getlength
getlength: 1: parameter null or not set

모든 포탄이 그렇게하는 것은 아닙니다. Bourne 쉘이 해냈습니다. Korn (및 Almquist) 쉘은 첫 번째 매개 변수를 $1대신 사용 하도록 선택 했습니다. POSIX 결국, 보른 방법을 갔다 너무 kshash 유도체 (더 많은 것을에 나중에에 복귀 http://www.in-ulm.de/~mascheck/various/find/#shell ). 즉 sh, 시스템에 따라 Bourne, Almquist 또는 Korn 셸을 기반으로 한 오랜 시간 동안 첫 번째 인수가 $0또는 인지 여부를 알지 못했기 $1때문에 이식성을 위해 다음과 같은 작업을 수행해야했습니다.

sh -c 'echo foo in "$1"' foo foo

또는:

sh -c 'shift "$2"; echo txt files are "$@"' tentative-arg0 3 2 *.txt

고맙게도 POSIX는 첫 번째 인수가 들어가는 새로운 동작을 지정 $0했으므로 이제 다음을 수행 할 수 있습니다.

sh -c 'echo txt files are "$@"' meaningful-arg0-for-error *.txt

방금 bash -c 'echo txt files are "$@"' meaningful-arg0-for-error *.txt우분투 14.04에서 bash를 실행 version 4.3.11(1)-release했으며 다음과 같은 결과를 얻었습니다 txt files are *.txt. Oo
muru

2
@muru는 정확 txt하며 현재 디렉토리에 파일 이 없을 수도 있습니다. 참조bash -c 'echo "${1?}"' foo
스테판 Chazelas가에게

아 예. 실제로 유용한 예입니다.
muru

1
sh -c 'shift "$2"; echo txt files are "$@"' tentative-arg0 3 2 *.txt환상적으로 독창적입니다!
iruvar

또는 완전히 강력한 해결 방법을 사용하십시오 (comp.unix.shell에서 Stéphane Chazelas가 제안) SHELL -c 'shift $1; command' 2 1 arg1 arg2 ... haha ...
mikeserv

3

이 동작은 POSIX에 의해 정의됩니다 .

sh -c command_name [인수 ...]

command_string 피연산자에서 명령을 읽습니다. command_name 피연산자 값 및 특수한 매개 변수 0 ( 특수 매개 변수 참조 ) 값을 나머지 인수 피연산자부터 순서대로 위치 매개 변수 ($ 1, $ 2 등)로 설정하십시오.

왜 당신이 그 행동을 원 할까 : 이것은 스크립트와 스크립트 사이의 간격을 부드럽게합니다. -c 문자열 합니다. 동작을 변경하지 않고 둘 사이를 직접 변환 할 수 있습니다. 다른 영역은 이것들이 동일하다는 것에 의존합니다.

또한 프로그램 인수가 일반적으로 작동하는 방식과 일치합니다. 이것은 궁극적으로 exec첫 번째 제공된 인수가 있는 함수 중 하나를 호출하는 것입니다.$0 하는 것과 관련이 있으며 일반적으로 해당 인수는 실행중인 실행 파일과 동일합니다. 그러나 때로는 특별한 가치를 원하며 다른 방법으로는 얻을 수 없습니다. 인수가 존재하면 무언가에 맵핑해야하며 사용자는 그 값을 설정할 수 있어야합니다.

이러한 일관성 (및 역사적 사고 가능성)은 찾은 상황으로 이어집니다.


두 번째 단락의 (실제로 현실적으로) 예를 들어 줄 수 있습니까?
muru

와 유추에주의하십시오 argv[0]. $0단지로 설정되어 argv[0]전달 execve()이 같은 때 shbash. 스크립트의 경우, $0해석기 (및 첫 번째 경로 인수에서 execve ()까지 오는 스크립트)에 대해 인수 1, 2 ...로 지정된 경로로 설정됩니다.
Stéphane Chazelas
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.