Позиционные параметры в скрипте читаются с помощью встроенного в zsh исходного кода - PullRequest
1 голос
/ 21 сентября 2011

Я заметил странное поведение при поиске другого скрипта в моем скрипте оболочки.Сценарий, который я использую для настройки среды в моем сценарии оболочки, принимает необязательный аргумент, например

source setup.sh version1

Однако в моем сценарии оболочки также есть переменные аргумента командной строки.Например:

./myscript.sh TEST 1

Внутри myscript.sh:

#!/bin/zsh
source setup.sh
echo ROOT version setup $ROOT_SYS
...more of the script

Проблема, которую я заметил в моем сценарии выше, заключается в том, что аргумент $1 (TEST в этом примере) используется в команде source setup.sh.Это приводит к тому, что команда становится

source setup.sh TEST

, что, конечно, дает сбой, поскольку setup.sh не имеет версии TEST.

Я решил эту проблему, отредактировав свой скрипт ниже.

#!/bin/zsh
source setup.sh version1
echo ROOT version setup $ROOT_SYS
...more of the script

Команда source теперь не принимает аргумент $1.

Почему / Как команда source получает аргумент $ 1, когда я запускаю свой скрипт оболочки?

Ответы [ 2 ]

3 голосов
/ 22 сентября 2011

Исторически, оболочки Unix не позволяли передавать аргументы в сценарии, вызываемые встроенным . (source - это псевдоним ., доступный в bash, ksh и zsh). Встроенный . означает «действовать так, как если бы этот файл действительно был включен здесь».

В bash, ksh и zsh, если вы передаете дополнительные аргументы встроенному ., они становятся позиционными параметрами ($1 и т. Д.) В исходном скрипте. Если вы передаете ноль аргументов, позиционные параметры основного скрипта остаются в силе. В этих оболочках . ведет себя скорее как вызов функции, хотя и не совсем так (в частности, в bash, если вы изменяете позиционные параметры внутри подпрограммы, изменение видится основным сценарием).

Простой способ избежать такого рода трудностей состоит в том, чтобы только когда-либо определять функции (и, возможно, переменные) в нижнем индексе. Обращайтесь с ней как с библиотекой кода, так что простое получение ее не даст никакого эффекта, а затем вызовите функции из подпрограммы, чтобы действительно что-то сделать.

2 голосов
/ 21 сентября 2011

Это потому, что источник выполняет код setup.sh, как если бы он был на месте, поэтому, когда setup.sh обращается, скажем, к $1, его значение равно первому аргументу фактического скрипта. Если вы хотите избежать этого, вы можете либо выполнить его:

setup.sh

или, если вам нужно получить из него некоторые переменные или значения, измените его, чтобы он возвращал результат в форме вывода, например:

ROOT_SYS=`setup.sh`

Наконец, как вы выяснили, ключевые слова source также позволяют предоставлять аргументы сценариям, но они пропускают текущие аргументы, если вы их не предоставляете.

...