Bash, предупреждение об отсутствии аргументов и решения по делу

110

Я изучаю баш.

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

Я также хотел бы узнать предложения лучших онлайн-руководств для начинающих по bash

Спасибо

Открыть путь
источник

Ответы:

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

case "$1" in
    1) echo 'you gave 1' ;;
    *) echo 'you gave something else' ;;
esac

Руководство по Advanced Bash-Scripting Guide довольно хорошее. Несмотря на название, он лечит основы.

Томас
источник
RE: «выход 0». Не знаю, имел ли он в виду выход из сценария. Но да, это отличный гид.
Trampas Kirk,
Я интерпретировал «и» как «иначе», предполагая, что сообщение будет некоторым справочным текстом. Но я уверен, что Вернер может понять, что делает эта строчка и хочет ли он этого :)
Томас,
спасибо конечно! и последнее: как отключить сообщения об ошибках в сценарии, чтобы они не отображались в оболочке?
Откройте путь
Вы имеете в виду ошибки, возникающие из конкретной программы, которую вы вызываете? Вы можете оставить > /dev/nullи / или 2> /dev/nullпосле этого отправить его стандартный вывод и / или стандартные потоки ошибок в забвение.
Thomas
4
Если вы считаете отсутствующий аргумент чем-то плохим (например, скрипт не может работать успешно), верните что-то отличное от 0 ( exit 1). Существуют и другие соглашения о кодах возврата / выхода, которые вы можете быстро найти в Интернете, но важным моментом является то, что он не должен быть равен 0, что означает успех.
Феликс
25

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

#!/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
Пэт
источник
11

пример

 if [ -z "$*" ]; then echo "No args"; fi

Результат

No args

подробности

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

Используйте man bashи найдите ( клавиша / ) "унарный", чтобы найти другие подобные операторы.

Trampas Кирк
источник
7
Проблема (незначительная) заключается в том, что он не различает передачу без аргументов и передачу пустой строки в качестве аргумента. Это может быть важно в некоторых случаях. Используя [$ # -eq 0], можно правильно обработать оба случая.
Idelic,
1
Ах, тонкости программирования (ба) ш ... Вот почему я его ненавижу.
Thomas
1
Думай о -zчем-то странном
Рэй Фосс
4

Старый, но теперь у меня есть причина переработать ответ из-за некоторой предыдущей путаницы:

if [[ $1 == "" ]] #Where "$1" is the positional argument you want to validate 

 then
 echo "something"
 exit 0

fi

Это будет эхо «Что-то», если нет позиционного аргумента $ 1. Однако это не подтверждает, что $ 1 содержит конкретную информацию.

Райан Смит
источник
$#явно является целым числом аргументов; либо это будет «0», и вы будете выводить эхо «что-то», даже если нет аргументов, либо это будет некоторое положительное число, и вы отобразите «что-то» правильно. Но сама проверка никогда ничего не сделает, вне зависимости от того, какой ввод или его нет - он всегда будет сообщать, что $#содержит значение. Так что это совершенно неправильно и никогда не будет работать так, как заявлено.
eschwartz
Вы полностью уверены в этом? У меня есть несколько скриптов, которые работают как задумано с использованием именно этого формата. Прочитав ваш ответ, я даже перепроверил и совпадение, и его отсутствие. $ # не будет содержать значение, если оно не указано, если нет позиционного аргумента, который бы соответствовал тому, что когда-либо было в вашем сценарии. Не имеет смысла, почему bash принимает значение в позиционном аргументе, которого нет.
Райан Смит
Попробуйте echo $#в качестве содержимого скрипта /tmp/test.sh, затем запустите его в / bin / bash, а также в / bin / sh (или / bin / dash и в любых других доступных вам реализациях оболочки. /tmp/test.shОтобразится «0» до консоль, как и будет /bin/dash /tmp/test.sh. С другой стороны, /tmp/test.sh fooбудет /tmp/test.sh first second
отображаться
В соответствии man bashс разделом «Специальные параметры», «Оболочка обрабатывает несколько параметров особым образом. На эти параметры можно только ссылаться; присвоение им недопустимо.» И «# Расширяется до количества позиционных параметров в десятичной системе счисления». Это также предусмотрено POSIX, как описано в pubs.opengroup.org/onlinepubs/9699919799/utilities/…
eschwartz
Извините, похоже, возникло недопонимание! Я имел в виду # как заполнитель для конкретного позиционного аргумента (например, $ 2, если вы имели в виду второй аргумент), а не буквального $ #. После просмотра вашего вышеупомянутого вы абсолютно правы, буквальный $ # всегда будет соответствовать количеству аргументов. Приносим извинения за путаницу.
Райан Смит