Обычно $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
она используется для определения поведения программ (а-ля, bash
называемых sh
или vim
называемых как vi
), но этого не может быть, поскольку $0
здесь это видно только в командной строке, а не в программах, вызываемых внутри нее. Я не могу думать ни о каком другом использовании для $0
, поэтому я затрудняюсь объяснить это.
-
для$0
аргумента как идиомы, как и вsh -c 'foo $1 $2' - a b
. Таким образом, это выглядит довольно нормально (как только вы узнали, что это-
значит, то есть)echo 'echo the other side of this pipe globs "$@"' | sh -s -- *
, хотя, к сожалению,$0
обычно это не настраиваемый параметр с параметром-s
tream ... Хотя, в общем, его можно использовать многими из тех же способовxargs
. И другие, кроме того.--
то, что могло бы иметь обычную интерпретацию «отсюда начинаются аргументы», что можно увидеть в некоторых других программах. Опять же, это может сбить с толку тех, с кем мы не знаем,-c
что на--
самом деле такое толкование есть.Ответы:
Это дает вам возможность устанавливать / выбирать
$0
при использовании встроенного скрипта. Иначе$0
бы просто былоbash
.Тогда вы можете сделать, например:
Не все снаряды делали это. Оболочка Борна сделала. Оболочка Korn (и Almquist) предпочла, чтобы
$1
вместо нее использовался первый параметр . POSIX в конце концов пошел на пути Борна, такksh
иash
производные вернулись к тому , что позже (подробнее об этом в http://www.in-ulm.de/~mascheck/various/find/#shell ). Это означало, что долгое времяsh
(который, в зависимости от системы, основывался на оболочке Bourne, Almquist или Korn), вы не знали, был ли введен первый аргумент,$0
или$1
, поэтому для переносимости, вам приходилось делать что-то вроде:Или:
К счастью, POSIX указал новое поведение, в котором
$0
вводится первый аргумент , так что теперь мы можем переносить:источник
bash -c 'echo txt files are "$@"' meaningful-arg0-for-error *.txt
на Ubuntu 14.04, Башversion 4.3.11(1)-release
, и я получил:txt files are *.txt
. Ооtxt
файлов в текущем каталоге). Смотрите такжеbash -c 'echo "${1?}"' foo
sh -c 'shift "$2"; echo txt files are "$@"' tentative-arg0 3 2 *.txt
это фантастически изобретательно!SHELL -c 'shift $1; command' 2 1 arg1 arg2 ...
хаха ...Это поведение определяется POSIX :
Что касается того, почему вы хотите такое поведение: это сглаживает разрыв между скриптом и
-c
строкой. Вы можете напрямую конвертировать между ними без каких-либо изменений в поведении. Другие области полагаются, что они идентичны.Это также согласуется с тем, как работают программные аргументы в целом: это в конечном итоге сводится к вызову одной из
exec
функций, в которой также указан первый предоставленный аргумент$0
, и в равной степени обычно этот аргумент совпадает с исполняемым файлом, который вы запускаете. Иногда, тем не менее, вам нужна особая ценность, и другого способа получить ее просто не было. Учитывая, что аргумент существует, он должен сопоставляться с чем-то, и пользователь должен иметь возможность установить, что это такое.Эта последовательность (и, вероятно, историческая случайность) приводит к ситуации, которую вы найдете.
источник
argv[0]
.$0
устанавливается только дляargv[0]
переданного,execve()
когда это какsh
илиbash
. Для сценариев$0
задается путь, заданный в качестве аргумента 1, 2 ... для интерпретатора (а для сценариев, выполняемых напрямую, который идет от первого аргумента пути к execve ()).