Позиционные параметры командной строки
Позиционные параметры командной строки
Cуществуют переменные четырех типов, переменные интерпретатора команд, переменные среды, а также переменные двух других типов, которые являются специальными, поскольку они предназначены только для чтения. Существуют позиционные и специальные параметры, они же переменные($, $@, $#, $$, $!, $?, $-), что есть "параметр", класическое определение звучит как: Параметр - это сущность, хранящая значение, параметром может быть имя, число или один из специальных символов "Специальных параметров", что есть "позиционный параметр" - это параметр, он же переменная, обозначаемая одной или несколькими цифрами (не больше девяти последовательных позиций в командной строке), кроме цифры 0, далее .......
Позиционные параметры.,
Сценарию, возможно передавать информацию с помощью позиционных параметров. Каждый параметр передает сценарию заданное количество ссылок (значений). Можно передавать произвольное число параметров(аргументов), но доступными (то есть имеющие значения) являются только первые девять из них, это ограничение преодолевается путем использования команды shift. Нумерация параметров начинается с единицы и завершается девятью; каждый параметр, доступ к которому возможно получить (поскольку они переменные), предваряется знаком переменной $. Первый параметр, он же "специальный", имеющий номер ноль $Ø, резервируется для представления действительного названия сценария, это значение может использоваться независимо от того, содержатся ли в сценарии позиционные параметры или нет.
Ниже в качестве примера демонстрируется, как можно получить доступ к каждому параметру, если в сценарий передается строка ¨Did You See The Full Moon¨
$Ø $1 $2 $3 $4 $5 $6 $7 $8 $9
Имя сценария: param Did You See The Full Moon
Применение в сценариях позиционных параметров
Воспользуемся приведенным выше примером в следующем сценарии.
#!/bin/sh
#param
#параметры
echo "This is the script name : $Ø"
echo "This is the first parameter : $1"
echo "This is the second parameter : $2"
echo "This is the third parameter : $3"
echo "This is the fourth parameter : $4"
echo "This is the fifth parameter : $5"
echo "This is the sixth parameter : $6"
echo "This is the seventh parameter : $7"
echo "This is the eighth parameter : $8"
echo "This is the ninth parameter : $9"
Результат:
$ sh param Did You See The Full Moon
This is the script name : param
This is the first parameter : Did
This is the second parameter : You
This is the third parameter : See
This is the fourth parameter : The
This is the fifth parameter : Full
This is the sixth parameter : Moon
This is the seventh parameter :
This is the eighth parameter :
This is the ninth parameter :
$
$ cat > mnemonika
if [ -n "$1" ]; then k=`echo Каждый`; fi
if [ -n "$2" ]; then o=`echo охотник`; fi
if [ -n "$3" ]; then j=`echo желает`; fi
if [ -n "$4" ]; then z=`echo знать`; fi
if [ -n "$5" ]; then s=`echo 'где сидит'`; fi
if [ -n "$6" ]; then b=`echo голубой`; fi
if [ -n "$7" ]; then f=`echo фазан`; fi
echo $k\($1\) $o\($2\) $j\($3\) $z\($4\) $s\($5\) $b\($6\) $f\($7\)
^C
$ . mnemonika "красный" "оранжевый" "желтый" "зеленый" "синий" "голубой" "фиолетовый"
Каждый(красный) охотник(оранжевый) желает(желтый) знать(зеленый) где сидит(синий) голубой(голубой) фазан(фиолетовый)
$ . mnemonika "1" "2" "3" "4" "5" "6" "7"
Каждый(1) охотник(2) желает(3) знать(4) где сидит(5) голубой(6) фазан(7)
$
Команда shift, расширит возможности применения "позиционных параметров", добавим в сценарий цикл while:
$ cat mnemonika
if [ -n "$1" ]; then k=`echo Каждый`; fi
if [ -n "$2" ]; then o=`echo охотник`; fi
if [ -n "$3" ]; then j=`echo желает`; fi
if [ -n "$4" ]; then z=`echo знать`; fi
if [ -n "$5" ]; then s=`echo 'где сидит'`; fi
if [ -n "$6" ]; then b=`echo голубой`; fi
if [ -n "$7" ]; then f=`echo фазан`; fi
echo $k\($1\) $o\($2\) $j\($3\) $z\($4\) $s\($5\) $b\($6\) $f\($7\)
loop=0; while [ $# -ne 0 ]; do echo $@; shift 2; done;
$ sh mnemonika "1" "2" "3" "4" "5" "6" "7" "8" "9" "10" "11" "12"
Каждый(1) охотник(2) желает(3) знать(4) где сидит(5) голубой(6) фазан(7)
1 2 3 4 5 6 7 8 9 10 11 12
3 4 5 6 7 8 9 10 11 12
5 6 7 8 9 10 11 12
7 8 9 10 11 12
9 10 11 12
11 12
$
Можно заметить, что добавлено двенадцать параметров строки, двенадцать поскольку shift равен 2 (четное число, 12 тоже четное), а условие гласит, что до 0 (сдвиг должен быть [ $# -ne 0 ]),то есть в противном случае цикл войдет в бесконечность (shift: can't shift that many),без значения сдвигается на одну позицию.
PS: Shift, конечно расширяет возможности применения параметров, но в сочетании с getops даст просто "волшебные" результаты, то есть позволит не только преодолеть ограничение на кол-во параметров ($!....$9) но и обработывать различные опции командной строки, как вам угодно (в пределах языка оболочки).
$ cat > opps
while getopts kojzsgf option; do
case "$option" in
k) k="Каждый" ;;
o) o="охотник" ;;
j) j="желает" ;;
z) z="знать" ;;
s) s="где сидит" ;;
g) g="голубой" ;;
f) f="фазан" ;;
t) t=$OPTARG; echo $OPTARG ;;
?) echo "Неизвестная опция $OPTARG" ;;
:) echo "Не передано значение для опции $OPTARG" ;;
*) echo "Произошла неизвестная ошибка" ;;
esac
done
echo $k $o $j $z $s $g $f
^C
$ sh opps -kzsf
Каждый знать где сидит фазан
$ sh opps -ozsf
охотник знать где сидит фазан
$ sh opps -kf
Каждый фазан
$ sh opps -kojzsgf
Каждый охотник желает знать где сидит голубой фазан
$ sh opps -kojzsgf -t "Mnemonika:"
Mnemonika:
Каждый охотник желает знать где сидит голубой фазан
Заметим, что в первом сценарии первый параметр содержит название сценария. Этот параметр удобно использовать, если сценарий выдает сообщение об ошибках. Ниже приводится пример, как получить название сценария:
#!/bin/sh
#param2
echo "Hello world this is $0 calling"
Результат:
$ sh param2
Hello world this is param2 calling
$
Циклы
Для перебора позиционных параметров чаще используют просто циклы while и for вместе с shift:
Цикл for без счетчика, по списку, количеству аргуменов - $#
$ cat > ffor
for argument; do
echo "$argument"
done
^C
$ . ffor r t y
r
t
y
Со счетчиком
$ for ((var=1; var <= LIMIT ; var++)); do echo $var; done
Сдвиг при помощи shift и проверка значения переменной $1 с помощью команды test
$ cat > wwhile
while [ "$1" ]; do
echo "$1"
shift
done
^C
$ . wwhile r t y u
r
t
y
u
Используя альтернативное значение: https://wiki.bash-hackers.org/syntax
$ cat > wwwhile
while [ "${1+defined}" ]; do
echo "$1"
shift
done
^C
$ . wwwhile r t y
r
t
y
Передача параметров в системные команды
Ниже пример как один из вариантов (многочисленных) как параметры можно передать внутри сценария в системную команду. В следующем примере используется команда find. Параметр $1 указывает имя файла для поиска.
$ pg findfile
#!/bin/sh
# findfile
find / -name $1 -print
$
$ findfile passwd
/etc/passwd
/etc/uucp/passwd
/usr/bin/passwd
$
Специальные параметры
Специальные параметры интерпретатора shell: При выводе данных с помощью специальных параметров можно получить много полезной информации о сценарии. Существует возможность проверить, какое число аргументов передается, а также идентификатор процесса этого сценария в том случае, если нужно уничтожить сценарий.
Код завершении последней команды
echo $?
Этот прием можно использовать во всех командах или сценариях, если необходимо выяснить, успешно ли выполнена последняя команда. С помощью этой информации можно продолжить работу со сценарием. Если возвращается значение Ø, значит все идет успешно; значение 1 означает появление ошибки.
Сценарии функционируют с помощью системных команд и сообщение о ошибках предусмотрено по умолчанию но обычно пользователь не заинтересован в отображении большого количества значений. Поэтому выходной поток перенаправляется в системную корзину /dev/null. Каким образом пользователь узнает, что последняя команда была успешной? С помощью кода завершения последней команды. Рассмотрим пример, иллюстрирующий изложенный материал.Скопируем файл ok.txt в не существующий каталог:
$ ср ok.txt /usr/locаl/spps/dsf >/dev/null 2>&1
$ echo $?
1
Если данные вывода, включая сообщения об ошибках, перенаправить в системную корзину, невозможно установить, выполнялась ли последняя команда. Но благодаря применению параметра $?, который возвращает значение 1, становится понятно, что при выполнении команды были допущены ошибки.
При проверке в сценариях кода завершения удобно проверяемым операциям присваивать содержательные названия. Желательно, чтобы название отражало функции данной операции; кроме того, сценарии приобретут более структурированный вид.
$ ср ok.txt /usr/locаl/spps/dsf >/dev/null 2>&1
$ cp_status=$?
$ echo $cp_status
1
Передача параметров сценарию
Рассмотрим сценарий в котором используются два параметра start и stop (взятые исключительно для примера) реализовано это все на конструкции case - многовариантном операторе или операторе выбора, если они не заданы выводится предупреждений. Сценарий призван показать , что для работы с командными опциями приходится создавать большой объем кода (в нашем случае имеются лишь две: start и stop) и что всё это обходится командой shift, при помощи которой можно выбирать различные опции, для понимания проблемы возможно стоит обратить внимание на то,что если вводить в качестве второго параметра:...something (..а вводить надо два), выполняться будет только параметр прописанный в коде.
$ ~ vim opt
#!/bin/bash
#opt
usage()
{
echo "Usage: `basename $0` ... start | stop process name"
}
OPT=$1
PROCESSID=$1
if [ $# -ne 2 ]
then
usage
exit 1
fi
case $OPT in
start | Start) echo "Starting..$PROCESSID"
;;
stop | Stop) echo "Stopping..$PROCESSID"
;;
*) usage
;;
esac
$ ~ opt
Usage: opt ... start | stop process name
$ ~
$ ~ opt stop ...something
Stopping..stop
$ ~
$ ~ opt start ...something
Starting..start
$ ~
$ ~ opt ...something
Usage: opt ... start | stop process name
$ ~
$ ~ opt start stop
Starting..start
$ ~
[17:30@solaris]~ # cat count_lines
#!/bin/bash
if test -a $1
then
echo "Number of lines in file " $1
wc -l $1
else
echo "the file" $1 "does not exist"
fi
[17:30@solaris]~ # chmod +x count_lines
[17:27@solaris]~ # PATH=$PATH:~
[17:27@solaris]~ # count_lines /etc/group
Number of lines in file /etc/group
23 /etc/group
[17:27@solaris]~ # count_lines /etc/grous
the file /etc/grous does not exist
[17:28@solaris]~ #
[18:19@solaris]~ # cat count_lines_1
#!/bin/bash
if test -r $1
then
echo "I can read the file " $1
else
echo "I can t read the file" $1
fi
[18:20@solaris]~ # count_lines_1 /etc/group
I can read the file /etc/group
[18:21@solaris]~ # count_lines_1 /etc/grous
I can t read the file /etc/grous
[18:21@solaris]~ #
-bash-3.2$ count_lines_1 /etc/shadow
I can t read the file /etc/shadow
-bash-3.2$ su
Password:
[18:26@solaris]~ # count_lines_1 /etc/shadow
I can read the file /etc/shadow
[18:26@solaris]~ #
=========================================================
Работа с переменными значительно облегчает функционирование интерпретатора shell. Автоматизируется ввод данных, повышается скорость работы. Переменная интерпретатора shell может принимать произвольные значения. Использование специальных переменных расширяет функциональные возможности сценариев и позволяет получать больше информации о параметрах, передаваемых в сценарии.