Одной из основных функций Bash является определение количества аргументов, переданных скрипту.

Причиной этого является возможность изменять поведение вашего скрипта в зависимости от значения и количества переданных ему аргументов.

Как узнать количество аргументов в Bash?

Bash предоставляет встроенную переменную $#, которая содержит количество аргументов, переданных скрипту. Распространенный способ использования $# — проверка ее значения в начале скрипта Bash, чтобы убедиться, что пользователь передал ему правильное количество аргументов.

В этой статье я покажу вам, как использовать переменную $# для просмотра количества аргументов, переданных скрипту. Мы также проверим, что количество переданных аргументов является правильным.

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

Начнем!

Распечатать количество аргументов, переданных скрипту Bash

Мы создадим очень простой скрипт Bash, который выведет в терминале количество переданных ему аргументов.

Вот код скрипта, который называется arguments.sh

#!/bin/bash

echo $#

Установите права на выполнение для скрипта, чтобы иметь возможность запустить его через терминал. Для этого используйте команду chmod:

chmod +x arguments.sh

Вот вывод скрипта, когда я передаю ему другое количество аргументов:

$./arguments.sh
0
$./arguments.sh test1
1
$./arguments.sh test1 test2
2

Как видите, значение встроенной переменной $# содержит количество аргументов, которые я передаю из терминала при запуске скрипта.

Давайте сделаем еще один шаг вперед!

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

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

Что может произойти, если пользователь введет только одно число, а я все равно попытаюсь посчитать сумму?

Давайте посмотрим…

В первой версии моего скрипта я просто вычисляю сумму двух чисел без какой-либо дополнительной проверки аргументов:

#!/bin/bash

num1=$1
num2=$2
sum=$(($1+$2))
echo $sum

$1, $2 … $N — встроенные переменные Bash, используемые для указания значения первого, второго и n-го аргумента, передаваемого в скрипт Bash.

Вот вывод, если я передам ему два аргумента:

$./sum.sh 1 2
3

Скрипт работает хорошо, так стоит ли мне что-то еще добавлять в него?

Давайте посмотрим, что произойдет, если я не предоставлю никаких аргументов своему скрипту:

$./sum.sh 
./sum.sh: line 5: +: syntax error: operand expected (error token is "+")

Скрипт выдает синтаксическую ошибку, поскольку ожидает операнд. В конце концов, мы хотим вычислить сумму двух чисел.

А что произойдет, если я передам один аргумент?

$./sum.sh 1
./sum.sh: line 5: 1+: syntax error: operand expected (error token is "+")

Точно такая же ошибка.

Как этого избежать?

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

Для этого мы можем использовать оператор if , который проверяет значение переменной $#.

Снова…

Переменная $# содержит количество аргументов, переданных скрипту Bash.

Мы обновим наш скрипт, чтобы сначала проверить, что количество аргументов, передаваемых пользователем, равно двум:

#!/bin/bash
  
if [ $# -ne 2 ]; then
    echo The number of arguments provided is incorrect. Please provide two numbers.
    exit 1
fi

num1=$1
num2=$2
sum=$(($1+$2))
echo $sum

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

В последнем выполнении вы можете видеть, что, как и ожидалось, скрипт работает хорошо с двумя аргументами:

$./sum.sh 
The number of arguments provided is incorrect. Please provide two numbers.
$./sum.sh 1
The number of arguments provided is incorrect. Please provide two numbers.
$./sum.sh 1 2 3
The number of arguments provided is incorrect. Please provide two numbers.
$./sum.sh 1 2
3

Видите, как я останавливаю выполнение скрипта после вывода сообщения об ошибке?

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

В Bash код выхода 0 соответствует успешному завершению, а коды выхода, отличные от 0, соответствуют неудаче.

Улучшение сообщения об ошибке на основе количества аргументов

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

Сообщение об ошибке будет другим, если пользователь не передаст ни одного аргумента, передаст один аргумент или более двух аргументов в скрипт Bash.

На этот раз вместо использования простого оператора if я буду использовать оператор if elif, учитывая, что я хочу проверить три различных условия:

#!/bin/bash
  
if [ $# -eq 0 ]; then
    echo You have provided zero arguments. Two are required.
    exit 1
elif [ $# -eq 1 ]; then
    echo You have provided one argument. Two are required.
    exit 2
elif [ $# -gt 2 ]; then
    echo You have provided more than two arguments. Two are required.
    exit 3
fi

num1=$1
num2=$2
sum=$(($1+$2))
echo $sum

В первой версии нашего скрипта мы только проверяли, не равно ли число аргументов двум, и для этого использовали оператор числового сравнения -ne, который означает «не равно».

На этот раз мы используем следующие операторы:

  • Оператор -eq (равно): проверяет, равно ли значение $# определенному значению.
  • Оператор -gt (больше чем): проверяет, больше ли значение $# указанного значения, в данном случае двух.

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

Найдите количество аргументов, переданных функции Bash

Мы увидели, как проверить количество аргументов, переданных в скрипт Bash.

Другой сценарий, в котором мы передаем аргументы в Bash, — это вызов функции.

Давайте посмотрим, как узнать количество аргументов, переданных функции Bash!

Я реорганизую наш скрипт, чтобы создать функцию под названием calculate_sum() вместо вычисления суммы в «основной» части скрипта.

Функция принимает два аргумента, вычисляет их сумму и возвращает результат:

#!/bin/bash
  
calculate_sum() {
    sum=$(($1+$2))
    return $sum
}

if [ $# -ne 2 ]; then
    echo The number of arguments provided is incorrect. Please provide two numbers.
    exit 1
fi

num1=$1
num2=$2
calculate_sum num1 num2
echo $?

Вот как работает этот скрипт:

  1. Определите функцию calculate_sum() в начале скрипта.
  2. Вызовите функцию, передав ей переменные num1 и num2.
  3. Выведите возвращаемое значение функции, используя переменную $?.

Если я хочу увидеть количество аргументов, переданных функции, я могу использовать точно такую ​​же переменную, которую мы использовали для вывода количества аргументов, переданных скрипту: $#.

Обновите функцию так, чтобы она выводила значение $#, чтобы мы могли подтвердить правильность значения (мы передаем функции два аргумента):

calculate_sum() {
    echo The number of arguments passed to the function is: $#
    sum=$(($1+$2))
    return $sum
}

И если я запущу скрипт, то увижу, что функция получает два аргумента при вызове:

$./sum.sh 1 2
The number of arguments passed to the function is: 2
3

Имеет ли это смысл?

Заключение

В этом уроке мы узнали, как получить количество аргументов, переданных в скрипт Bash. Мы также увидели, как использовать эту информацию, чтобы сделать наш скрипт более надежным.

Проверка, которую мы реализовали в начале скрипта, позволяет выполнить весь скрипт только в том случае, если скрипт получает правильное количество аргументов.

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

Вот почему так важно в первую очередь проверять количество аргументов во всех ваших скриптах.

Наконец, мы увидели, что переменную $# можно использовать в Bash для определения количества аргументов, переданных скрипту, а также функции.

Written by Иван Васильков

Системный администратор и DevOps с опытом 10+ лет.