Передача аргументов в скрипт

Передача аргументов в скрипт

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


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

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

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

Знак доллара, за которым следует число N, соответствует N-му аргументу, переданному скрипту. Если вы вызовете пример выше, то на ./test.shвыходе будет Hello Linux. $0Переменная содержит имя самого скрипта.

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


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

Любая помощь приветствуется.

решение1

Описание в книге неверное (или, по крайней мере, чего-то не хватает). Чтобы заставить этот скрипт напечатать "Hello Linux", вы должны запустить его так:

./test.sh Linux

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

./test.sh foo bar baz

то внутри скрипта $0будет "./test.sh", $1будет "foo", $2будет "bar" и $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".

Кстати, многие команды просто используют статусы выхода 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бы проверить $?, что пошло не так, и отреагировать по-разному в зависимости от проблемы.

решение2

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

КакГордон Дэвиссон сказал, автор книги, должно быть, имел в виду, что выполнение ./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 simplewhere simpleis заменен на имя файла, если оно отличается. Затем вы можете запустить его с помощью команд вроде ./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.

решение3

Одна хорошая книга, о которой вам следует знать, — это «Командная строка Linux» Уильяма Шоттса, опубликованная издательством No Starch Press и доступная в виде бесплатного 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.

Связанный контент