Позиционные параметры командной строки

Позиционные параметры командной строки 

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 может принимать произвольные значения. Использование специальных переменных расширяет функциональные возможности сценариев и позволяет получать больше информации о параметрах, передаваемых в сценарии.