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

748

Мне нужно проверить наличие входного аргумента. У меня есть следующий скрипт:

if [ "$1" -gt "-1" ]
  then echo hi
fi

я получил

[: : integer expression expected

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

Теги:

7 ответов

1266
Лучший ответ

Это:

if [ $# -eq 0 ]
  then
    echo "No arguments supplied"
fi

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

Или вы можете проверить, является ли аргумент пустой строкой или нет:

if [ -z "$1" ]
  then
    echo "No argument supplied"
fi

Переключатель -z проверяет, является ли расширение «$ 1» пустой строкой или нет. Если это пустая строка, тело выполняется.

  • 47
    Мне нравится делать это таким образом, с кратким синтаксисом и все еще приемлемым POSIX. [ -z "$1" ] && echo "No argument supplied" Я предпочитаю однострочники, так как они проще для меня; и это также быстрее проверить выходное значение, по сравнению с использованием, if
  • 140
    Возможно, вы захотите добавить exit 1 в конце вашего эха внутри блока if, когда для работы скрипта необходим аргумент. Очевидно, но стоит отметить полноту.
Показать ещё 8 комментариев
166

Лучше продемонстрировать этот способ

if [[ $# -eq 0 ]] ; then
    echo 'some message'
    exit 1
fi

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

  • 3
    Это дубликат принятого ответа, поэтому я считаю, что его следует удалить.
  • 62
    Нет, это не так: здесь есть exit 1 который вы обычно хотите, и используется тест [[ ]] который (iirc) обычно более целесообразен. Так что для людей, слепо копирующих код, это лучший ответ.
Показать ещё 2 комментария
50

Если вас интересует только обнаружение отсутствия какого-либо аргумента, подстановка параметров велика:

#!/bin/bash
# usage-message.sh

: ${1?"Usage: $0 ARGUMENT"}
#  Script exits here if command-line parameter absent,
#+ with following error message.
#    usage-message.sh: 1: Usage: usage-message.sh ARGUMENT

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

scale=${2:-1}
emulator @$1 -scale $scale

Здесь, если пользователь не передал scale в качестве второго параметра, я запускаю Android-эмулятор с -scale 1 по умолчанию. ${varname:-word} - оператор разложения. Существуют и другие операторы расширения:

  • ${varname:=word}, который устанавливает неопределенное varname вместо возвращения значения word;
  • ${varname:?message}, который либо возвращает varname, если он определен и не равен null, либо печатает message и прерывает скрипт (как в первом примере);
  • ${varname:+word}, который возвращает word, только если varname определен и не равен нулю; Возвращает null в противном случае.
  • 1
    В приведенном выше примере, похоже, используется ${varname?message} . Это лишнее : опечатка, или это меняет поведение?
  • 5
    Эки, ":" - это встроенная команда и сокращение для / bin / true в этом примере. Она представляет собой команду «ничего не делать», которая в основном игнорирует аргументы, которые она предоставляет. Это важно в этом тесте, чтобы не дать интерпретатору попытаться выполнить содержимое «$ varname» (что вы, конечно, НЕ хотите, чтобы это произошло). Также стоит отметить; с помощью этого метода вы можете протестировать столько переменных, сколько пожелаете. И все с конкретными сообщениями об ошибках. то есть : ${1?"First argument is null"} ${2?"Please provide more than 1 argument"}
24

Еще один способ определить, передавались ли аргументы скрипту:

((!$#)) && echo No arguments supplied!

Обратите внимание, что (( expr )) заставляет выражение вычисляться согласно правилам арифметики оболочки .

Чтобы выйти в отсутствие каких-либо аргументов, можно сказать:

((!$#)) && echo No arguments supplied! && exit 1

Другой (аналогичный) способ сказать выше:

let $# || echo No arguments supplied

let $# || { echo No arguments supplied; exit 1; }  # Exit if no arguments!

help let говорит:

let: let arg [arg ...]

  Evaluate arithmetic expressions.

  ...

  Exit Status:
  If the last ARG evaluates to 0, let returns 1; let returns 0 otherwise.
  • 1
    -1 это может быть наихудший метод при проверке существования аргумента ... плюс он может вызвать подстановку истории и потенциально может привести к ошибкам.
  • 1
    вместо exit который убивает мой процесс zsh, я использую return который не убивает его
19

Пытаться:

 #!/bin/bash
 if [ "$#" -eq  "0" ]
   then
     echo "No arguments supplied"
 else
     echo "Hello world"
 fi
  • 3
    Зачем вам двойные кавычки для $# и 0 ?
  • 1
    Нет проблем, если мы используем без двойных кавычек, как $ # и 0
Показать ещё 3 комментария
2

В качестве небольшого напоминания, числовые тестовые операторы в Bash работают только с целыми числами (-eq, -lt, -ge и т. Д.),

Мне нравится, чтобы мои $ vars были ints

var=$(( var + 0 ))

Перед тем, как протестировать их, просто для защиты от «[: integer arg required» error.

  • 1
    Неплохой трюк, но, пожалуйста, обратите внимание: из-за неспособности bash обрабатывать плавающие числа в арифметике, этот метод может вызвать синтаксическую ошибку и вернуть ненулевое значение, что будет помехой, если включен errexit. var=$(printf "%.0f" "$var") может обрабатывать числа с плавающей запятой, но страдает от ненулевого выхода при var=$(printf "%.0f" "$var") строки. Если вы не возражаете против awk, этот метод, который я использую, кажется, наиболее надежен для принудительного применения целого числа: var=$(<<<"$var" awk '{printf "%.0f", $0}') . Если переменная не установлена, по умолчанию используется значение «0». Если var - это число с плавающей точкой, оно округляется до ближайшего целого числа. Отрицательные значения также можно использовать.
1

Если вы хотите проверить, существует ли аргумент, вы можете проверить, больше ли число аргументов аргументов # или равно их числу.

Следующий script демонстрирует, как это работает

test.sh

#!/usr/bin/env bash

if [ $# -ge 3 ]
then
  echo script has at least 3 arguments
fi

выводит следующий вывод

$ ./test.sh
~
$ ./test.sh 1
~
$ ./test.sh 1 2
~
$ ./test.sh 1 2 3
script has at least 3 arguments
$ ./test.sh 1 2 3 4
script has at least 3 arguments

Ещё вопросы

Сообщество Overcoder
Наверх
Меню