Передающие аргументы сценарию

Я посещаю урок Основ Linux и преуспевал, пока я не поразил главу сценариев. Я просто не понимаю эти понятия. Удивление, если кто-то может разломать следующее на крайние упрощенные условия или указать на меня на лучшую ссылку для изучения этого. Я в настоящее время использую программу netacad.


Из учебника (с незначительными изменениями форматирования):

Существуют некоторые специальные переменные в дополнение к тем, Вы устанавливаете. Можно передать аргументы сценарию:

#!/bin/bash
echo "Hello $1"

Знак доллара, сопровождаемый номером N, соответствует Энному аргументу, переданному сценарию. Если Вы называете пример выше с ./test.sh выводом будет Привет Linux. $0 переменная содержит название самого сценария.

После прогоны программы, быть этим двоичный файл или сценарий, это возвращает код выхода, который является целым числом между 0 и 255. Можно протестировать это через $? переменная, чтобы видеть, если предыдущая команда, завершенная успешно.


Я понимаю, как присвоить переменные и как они работают с $ но целая проблема с $0 и $1 - Я просто не получаю его.

Любая справка очень ценилась бы.

5
задан 19 June 2019 в 07:05

3 ответа

Одной хорошей книгой, о которой необходимо знать, является William Shotts "Командная строка Linux", опубликованный Никаким Нажатием Крахмала и доступный как свободный PDF на веб-сайте автора.

В каждом сценарии оболочки существует набор пронумерованных переменных, которые обычно упоминаются как $1, $2, и т.д. Это "позиционные параметры", чаще всего известный как параметры командной строки. Можно думать о них как о названных переменных 1, 2, и т.д. и получить их значения, Вы использовали бы $1, $2, и т.д., Когда Вы называете сценарий названным my_script через командную строку ./my_script a b c, это получило бы три аргумента, которые хранятся в этих трех переменных $1, $2, и $3. Вы не можете присвоить этим переменным (за исключением группы), но можно исследовать и использовать их значения. Например, echo "$1" распечатал бы первый аргумент Вашему сценарию.

$0 немного необычно; это - имя, которым сценарий Вы работаете, был назван. В случае выше, это имело бы значение ./my_script. Снова, Вы видите, что это - значение, но не изменяют его.

$? "статус выхода" команды, которая просто работала. Если команда успешно выполнилась, то ее статус выхода будет 0 и иначе это будет маленькое положительное целое число. Можно выдержать сравнение $? обнулять, чтобы видеть если предыдущая команда, за которой следуют или неудавшийся. Например, следующие две командных строки будут работать grep команда и затем отзывается эхом <1> потому что grep отказавший и вышедший с состоянием 1 (указание, что это перестало работать).

grep blarg /etc/passwd
echo "<$?>"

Статус выхода полезен в записи простых сценариев как:

#!/bin/bash
# grep_pw: grep for a pattern in /etc/passwd
grep "$1" /etc/passwd
if [[ $? = 0 ]] ;then
  echo "Found it"
  exit 0
else
  echo "Unable to find the pattern '$1' in /etc/passwd"
  exit 1
fi

Помещенный, что текст в файл называют grep_pw, измените его, чтобы быть исполняемым файлом с chmod 700 grep_pw, и назовите его как ./grep_pw nologin найти строки в /etc/passwd которые содержат строку nologin.

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

#!/bin/bash
# echoargs: print all the arguments
counter=1
for a in "$@" ;do
   echo "arg $counter=<$a>"
   let counter=counter+1
done

Поместите то содержание в названный файл echoargs, измените его, чтобы быть исполняемым файлом с chmod 700 echoargs и назовите его как: ./echoargs a "b c" d.

1
ответ дан 19 June 2019 в 07:05

$0 имя, которое Вы используете для запущения скрипта. $1, $2, и т.д позиционные параметры сценария, которые содержат значения параметров командной строки, которые Вы передали, когда Вы запустили скрипт.

Как Gordon Davisson сказал, автор книги, должно быть, означал говорить то выполнение ./test Linux распечатал бы Hello Linux. Когда Вы делаете это, ./test входит к специальному параметру 0, и Linux переходит в в первый позиционный параметр 1. Сценарий разворачивает тот первый позиционный параметр путем предшествования ему со знаком доллара ($1), так же, как Вы делаете с переменными. Если Вы вместо этого работали ./test Hello Linux for Human Beings, затем в сценарии, $1 расширился бы до Linux, $2 кому: for, $3 кому: Human, и $4 кому: Beings.

Можно записать простой сценарий для испытания этого:

#!/bin/bash

echo "\$0 expands to '$0'."
echo "\$1 expands to '$1'."
echo "\$2 expands to '$2'."
echo "\$3 expands to '$3'."

(Продолжите насколько Вы хотите. Для позиционных параметров выше, чем 9, используйте ${ } форма расширения параметра, например, расширяется 10 путем записи ${10}. В сценариях, которые работают со многими позиционными параметрами, специальным параметром @ часто используется, избегая повторения, но можно проигнорировать, что на данный момент, если Вам нравится.)

Попытайтесь сохранить это в файле и отметить исполняемый файл файла, который можно сделать путем выполнения chmod +x simple где simple заменяется названием файла, если отличающийся. Затем можно выполнить его, использование управляет как ./simple, ./simple foo, ./simple foo bar, и так далее.

Вы заметите, что, когда меньше чем три параметра командной строки передаются, позиционные параметры, которые соответствуют тем, которые не были переданы, расширяются до пустой строки. Это - то, что происходит, когда Вы пытаетесь развернуть параметр оболочки, который не определяется. Вы заметите, далее, что, когда больше параметров командной строки передается, те мимо третьего не используются. Это, вероятно, что Вы ожидали бы, так как сценарий не относится к ним вообще.

Теперь попытайтесь работать ./simple *. Оболочка расширяется * ко всем именам файлов в текущем каталоге кроме тех, которые запускаются с ., таким образом, три из тех покажутся первыми тремя позиционными параметрами (или меньше, если не будет то, что многие). Можно попытаться выполнить его с другими расширениями оболочки, такой как ./simple {5..10}.

Можно передать параметры командной строки, содержащие пробелы путем включения их в кавычки. Например, попробовать ./simple 'foo bar' baz. Заметьте это $1 расширяется до foo bar на этот раз, и не только к foo.

Поскольку оболочка выполняет различные расширения, не всегда очевидно, сколько параметров командной строки Вы являетесь передающими к команде. Простой способ видеть, чем будет каждый аргумент, состоит в том, чтобы заменить команду printf '[%s]\n'. Например:

$ printf '[%s]\n' f*
[fonts]
[fstab]
[fuse.conf]
[fwupd]
$ printf '[%s]\n' {1,3}{a..c}
[1a]
[1b]
[1c]
[3a]
[3b]
[3c]

Так как Вы только недавно запустили сценарии оболочки, справочник Bash может быть сложным, и Вы не могли бы хотеть читать его по всей длине. Но я думаю, что это - ценный ресурс, даже если Вы считаете себя полным новичком. Можно найти раздел по параметрам оболочки полезным, так как он запускается с того, как что Вы уже знаете - переменные оболочки - и шаги к специальным параметрам ? (какие люди часто звонят $? параметр, так как это - то, как Вы разворачиваете его). Для общего приобретения знаний о Bash, особенно на более вводном уровне, я рекомендую эти страницы, включая BashGuide.

4
ответ дан 19 June 2019 в 07:05

Описание из книги является неправильным (или по крайней мере недостающим что-то). Чтобы заставить тот сценарий печатать "Привет Linux", Вы выполнили его как это:

./test.sh Linux

Если Вы выполняете его только с ./test.sh, затем это только распечатает "Привет", потому что был никакой первый аргумент и $1 не определяется. С другой стороны, предположите выполнение его как это:

./test.sh foo bar baz

затем в рамках сценария, $0 был бы "./test.sh", $1 было бы "нечто", $2 была бы "панель", и $3 был бы "baz".

Что касается $?, рассмотрите следующий отрывок сценария:

ls nonexistentfile.txt
echo "The exit status of ls was: $?"
echo "The exit status of echo (the first one) was: $?"

Когда выполнено это распечатает что-то как:

ls: nonexistentfile.txt: No such file or directory
The exit status of ls was: 1
The exit status of echo (the first one) was: 0

ls команда не может перечислить nonexistentfile.txt (потому что она не существует), таким образом, она печатает сообщение об ошибке к тому эффекту и выходит с ненулевым состоянием, чтобы указать, что что-то пошло не так, как надо. Первое echo управляйте печатает тот статус выхода ($?), и так как это делает это успешно, это выходит с состоянием нуля. Когда второе echo управляйте выполнениями, это добирается $? сначала echo команда, таким образом, это печатает "0".

BTW, много команд просто использует статусы выхода 0 (успех) или 1 (своего рода отказ), но некоторое использование различные состояния отказа для указания точно, что пошло не так, как надо. Вот выборка от curl страница руководства:

EXIT CODES
       There are a bunch of different  error  codes  and  their  corresponding
       error  messages  that  may appear during bad conditions. At the time of
       this writing, the exit codes are:

       1      Unsupported protocol. This build of curl has no support for this
              protocol.

       2      Failed to initialize.

       3      URL malformed. The syntax was not correct.

       ...

       88     FTP chunk callback reported error

       89     No connection available, the session will be queued

       90     SSL public key does not matched pinned public key

       91     Invalid SSL certificate status.

       92     Stream error in HTTP/2 framing layer.

... так сценарий, который использовал curl мог проверить $? выяснять, что пошло не так, как надо и отвечает по-другому в зависимости от проблемы.

7
ответ дан 19 June 2019 в 07:05

Другие вопросы по тегам:

Похожие вопросы: