Специальные переменные в Shell

ShellBeginner
Практиковаться сейчас

Введение

В этой лабораторной работе вы познакомитесь со специальными переменными в программировании на Shell. Эти переменные предоставляют важную информацию о среде выполнения скрипта, такую как аргументы командной строки, имя самого скрипта и идентификатор процесса. Понимание этих переменных поможет вам писать более гибкие и функциональные сценарии.

Создание первого скрипта

Начнем с создания простого shell-скрипта для демонстрации использования специальных переменных.

  1. Откройте терминал в WebIDE. Вы увидите приглашение командной строки, ожидающее ввода.

  2. Перейдите в каталог проекта:

cd ~/project

Эта команда меняет текущий каталог на ~/project, который является рабочим каталогом по умолчанию для этой лабораторной работы.

  1. Создайте новый файл с именем special_vars.sh с помощью следующей команды:
touch special_vars.sh

Команда touch создает пустой файл, если он не существует, или обновляет время его изменения, если он уже есть.

  1. Откройте файл в редакторе WebIDE. Для этого щелкните по имени файла в проводнике слева.

  2. Добавьте в файл следующее содержимое:

#!/bin/bash

echo "Script Name: $0"
echo "First Argument: $1"
echo "Second Argument: $2"
echo "All Arguments: $@"
echo "Number of Arguments: $#"
echo "Process ID: $$"

Разберем, что делает каждая строка:

  • #!/bin/bash: Это шебанг (shebang). Он указывает системе использовать bash для интерпретации этого скрипта.
  • $0: Эта специальная переменная хранит имя скрипта.
  • $1 и $2: Они представляют собой первый и второй аргументы командной строки соответственно.
  • $@: Представляет все аргументы командной строки, переданные скрипту.
  • $#: Возвращает количество переданных аргументов.
  • $$: Предоставляет идентификатор процесса (PID) текущей оболочки.
  1. Сохраните файл после добавления содержимого.

  2. Сделайте скрипт исполняемым, выполнив следующую команду в терминале:

chmod +x special_vars.sh

Команда chmod изменяет права доступа к файлу. Опция +x добавляет право на выполнение, что позволяет вам запускать скрипт.

Запуск скрипта с аргументами

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

  1. Запустите скрипт без аргументов:
./special_vars.sh

Символы ./ перед именем файла указывают оболочке искать скрипт в текущем каталоге.

Вы должны увидеть вывод, похожий на этот:

Script Name: ./special_vars.sh
First Argument:
Second Argument:
All Arguments:
Number of Arguments: 0
Process ID: 1234

Обратите внимание, что первый и второй аргументы пусты, а количество аргументов равно 0, так как мы ничего не передали.

  1. Теперь запустите скрипт с несколькими аргументами:
./special_vars.sh hello world

Вывод должен выглядеть так:

Script Name: ./special_vars.sh
First Argument: hello
Second Argument: world
All Arguments: hello world
Number of Arguments: 2
Process ID: 1235

Что изменилось:

  • $1 теперь содержит "hello"
  • $2 теперь содержит "world"
  • $@ показывает все аргументы: "hello world"
  • $# показывает 2, так как мы передали два аргумента

Идентификатор процесса ($$) может меняться при каждом запуске, так как он назначается операционной системой динамически.

Понимание $? и $!

Еще две важные специальные переменные — это $? и $!. Создадим новый скрипт для демонстрации их работы.

  1. Создайте новый файл с именем exit_status.sh:
touch ~/project/exit_status.sh
  1. Откройте файл в редакторе WebIDE и добавьте следующее содержимое:
#!/bin/bash

echo "Running a successful command:"
ls /home
echo "Exit status: $?"

echo "Running a command that will fail:"
ls /nonexistent_directory
echo "Exit status: $?"

echo "Running a background process:"
sleep 2 &
echo "Process ID of last background command: $!"

Разберем этот скрипт:

  • $? возвращает код завершения последней выполненной команды. 0 обычно означает успех, а любое другое значение указывает на ошибку.
  • $! возвращает идентификатор процесса (PID) последней команды, запущенной в фоновом режиме.
  • Символ & в конце команды запускает её в фоновом режиме.
  1. Сохраните файл и сделайте его исполняемым:
chmod +x ~/project/exit_status.sh
  1. Запустите скрипт:
./exit_status.sh

Вы увидите примерно такой вывод:

Running a successful command:
labex
Exit status: 0
Running a command that will fail:
ls: cannot access '/nonexistent_directory': No such file or directory
Exit status: 2
Running a background process:
Process ID of last background command: 1236

Обратите внимание:

  • Первая команда ls выполнена успешно, поэтому $? равен 0.
  • Вторая команда ls завершилась с ошибкой (так как каталог не существует), поэтому $? равен 2 (ненулевое значение, указывающее на ошибку).
  • Команда sleep работает в фоне, и $! показывает её PID.

Использование специальных переменных в функциях

Специальные переменные также можно использовать внутри функций. Создадим скрипт для проверки этого поведения.

  1. Создайте новый файл с именем function_vars.sh:
touch ~/project/function_vars.sh
  1. Откройте файл в редакторе WebIDE и добавьте следующее содержимое:
#!/bin/bash

function print_args {
  echo "Function Name: $0"
  echo "First Argument: $1"
  echo "Second Argument: $2"
  echo "All Arguments: $@"
  echo "Number of Arguments: $#"
}

echo "Calling function with two arguments:"
print_args hello world

echo "Calling function with four arguments:"
print_args one two three four

Этот скрипт определяет функцию print_args, использующую специальные переменные, и вызывает её дважды с разным количеством аргументов.

  1. Сохраните файл и сделайте его исполняемым:
chmod +x ~/project/function_vars.sh
  1. Запустите скрипт:
./function_vars.sh

Вывод будет примерно таким:

Calling function with two arguments:
Function Name: ./function_vars.sh
First Argument: hello
Second Argument: world
All Arguments: hello world
Number of Arguments: 2
Calling function with four arguments:
Function Name: ./function_vars.sh
First Argument: one
Second Argument: two
All Arguments: one two three four
Number of Arguments: 4

Заметьте, что:

  • $0 по-прежнему ссылается на имя скрипта, а не на имя функции.
  • $1, $2, $@ и $# работают для аргументов функции точно так же, как и для аргументов скрипта.
  • Значения этих переменных меняются при каждом вызове функции в зависимости от переданных ей данных.

Разница между $@ и $*

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

  1. Создайте новый файл с именем at_vs_star.sh:
touch ~/project/at_vs_star.sh
  1. Откройте файл в редакторе WebIDE и добавьте следующее содержимое:
#!/bin/bash

echo "Using \$@:"
for arg in "$@"; do
  echo "Argument: $arg"
done

echo "Using \$*:"
for arg in "$*"; do
  echo "Argument: $arg"
done

Этот скрипт демонстрирует различие между $@ и $* при использовании в цикле.

  1. Сохраните файл и сделайте его исполняемым:
chmod +x ~/project/at_vs_star.sh
  1. Запустите скрипт с несколькими аргументами, включая аргументы с пробелами:
./at_vs_star.sh "arg with spaces" another_arg "third arg"

Вывод будет выглядеть так:

Using $@:
Argument: arg with spaces
Argument: another_arg
Argument: third arg
Using $*:
Argument: arg with spaces another_arg third arg

Вот что происходит:

  • При использовании "$@" каждый аргумент обрабатывается как отдельный объект. Аргументы с пробелами сохраняются как единые элементы.
  • При использовании "$*" все аргументы объединяются в одну строку, разделенную первым символом переменной IFS (обычно это пробел).

Эта разница критически важна, когда вам нужно обрабатывать аргументы, которые могут содержать пробелы или другие специальные символы.

Резюме

В этой лабораторной работе вы изучили специальные переменные в Shell и научились эффективно их использовать. Вы создали скрипты, демонстрирующие работу таких переменных, как $0, $1, $@, $#, $$, $? и $!. Вы также узнали, как эти переменные ведут себя в различных контекстах, включая функции и обработку аргументов командной строки.

Основные выводы:

  1. $0, $1, $2 и т.д. представляют имя скрипта и его аргументы.
  2. $@ и $# позволяют работать со всеми аргументами сразу и узнавать их количество.
  3. $$ возвращает PID текущего процесса, что полезно для создания уникальных временных файлов.
  4. $? помогает проверить, успешно ли завершилась предыдущая команда.
  5. $! возвращает PID последнего фонового процесса, что удобно для управления задачами.
  6. "$@" и "$*" ведут себя по-разному при использовании кавычек, что важно для корректной обработки аргументов с пробелами.

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

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