Як я можу додати довідковий метод до сценарію оболонки?


Відповіді:


173

ось приклад для bash:

usage="$(basename "$0") [-h] [-s n] -- program to calculate the answer to life, the universe and everything

where:
    -h  show this help text
    -s  set the seed value (default: 42)"

seed=42
while getopts ':hs:' option; do
  case "$option" in
    h) echo "$usage"
       exit
       ;;
    s) seed=$OPTARG
       ;;
    :) printf "missing argument for -%s\n" "$OPTARG" >&2
       echo "$usage" >&2
       exit 1
       ;;
   \?) printf "illegal option: -%s\n" "$OPTARG" >&2
       echo "$usage" >&2
       exit 1
       ;;
  esac
done
shift $((OPTIND - 1))

Щоб використовувати це всередині функції:

  • використовувати "$FUNCNAME"замість$(basename "$0")
  • додати local OPTIND OPTARGдо дзвінкаgetopts

1
Я намагаюся це всередині функції, але коли я намагаюся запустити функцію, я отримую цю помилку "basename: invalid option -" b "". Схоже, він намагається передати "-bash" на basenameпровідну тире.
Морган Естес

5
"$FUNCNAME"не використовувати функцію використання не "$0". Також addlocal OPTIND OPTARG
glenn jackman

Дякую. FUNCNAMEпрацює. У мене є всі функції в одному файлі, тому це ідеально підходить для розширення їх на щось корисне для інших.
Morgan Estes

5
@sigur, переконайтесь, що ви цитуєте "$usage" кожне місце, де ви його використовуєте.
Глен Джекман

1
Для чого це shift $((OPTIND - 1))?
hpaknia

45

Перший аргумент скрипту оболонки доступний як змінна $1, тому найпростішою реалізацією було б

if [ "$1" == "-h" ]; then
  echo "Usage: `basename $0` [somestuff]"
  exit 0
fi

Але що сказала анубхава.


Дякуємо @MarkBooth, виправлено помилку (плюс покращення шляхом загортання лапок)
1313

Ви повинні звикнути обгортання if у [[]] для умовних умов, щоб уникнути неправильного розбору змінної, Джерело: github.com/bahamas10/bash-style-guide#bashisms
JREAM

2
Так, хоча OP не вказав bash і [є сумісною з POSIX версією.
seb

Примітка - Для використання всередині function: Ви повинні замінити exit 0з , returnякщо ви не хочете , щоб завершити свою оболонку після запуску функції. (Я робив це раніше 😂)
Освітлювач

29

ось частина, яку я використовую для запуску сервера VNC

#!/bin/bash
start() {
echo "Starting vnc server with $resolution on Display $display"
#your execute command here mine is below
#vncserver :$display -geometry $resolution
}

stop() {
echo "Killing vncserver on display $display"
#vncserver -kill :$display
}

#########################
# The command line help #
#########################
display_help() {
    echo "Usage: $0 [option...] {start|stop|restart}" >&2
    echo
    echo "   -r, --resolution           run with the given resolution WxH"
    echo "   -d, --display              Set on which display to host on "
    echo
    # echo some stuff here for the -a or --add-options 
    exit 1
}

################################
# Check if parameters options  #
# are given on the commandline #
################################
while :
do
    case "$1" in
      -r | --resolution)
          if [ $# -ne 0 ]; then
            resolution="$2"   # You may want to check validity of $2
          fi
          shift 2
          ;;
      -h | --help)
          display_help  # Call your function
          exit 0
          ;;
      -d | --display)
          display="$2"
           shift 2
           ;;

      -a | --add-options)
          # do something here call function
          # and write it in your help function display_help()
           shift 2
           ;;

      --) # End of all options
          shift
          break
          ;;
      -*)
          echo "Error: Unknown option: $1" >&2
          ## or call function display_help
          exit 1 
          ;;
      *)  # No more options
          break
          ;;
    esac
done

###################### 
# Check if parameter #
# is set too execute #
######################
case "$1" in
  start)
    start # calling function start()
    ;;
  stop)
    stop # calling function stop()
    ;;
  restart)
    stop  # calling function stop()
    start # calling function start()
    ;;
  *)
#    echo "Usage: $0 {start|stop|restart}" >&2
     display_help

     exit 1
     ;;
esac

Трохи дивно, що я помістив перезапуск запуску зупинки в окремий випадок, але це має працювати


якщо ви даєте порожній варіант -d; не буде це нескінченна петля?
zerobane

Чому ви виходите з 1 у функції помічника?
jeantimex

17

Для швидкого рішення з одним варіантом використовуйте if

Якщо у вас є лише один варіант перевірки, і це завжди буде перший варіант ( $1), тоді найпростішим рішенням є ifтест ( [). Наприклад:

if [ "$1" == "-h" ] ; then
    echo "Usage: `basename $0` [-h]"
    exit 0
fi

Зауважте, що для сумісності posix також =буде добре працювати ==.

Навіщо цитувати $1?

Причина, яку $1потрібно вкласти в лапки, полягає в тому, що якщо немає, $1оболонка спробує запуститись if [ == "-h" ]і вийти з ладу, тому що ==їй дали лише один аргумент, коли очікували двох:

$ [ == "-h" ]
bash: [: ==: unary operator expected

Для чого-небудь більш складного використання getoptабоgetopts

Як запропоновано на інших , якщо у вас є більш ніж один варіант простий, або потрібна ваша можливість прийняти аргумент, то ви повинні обов'язково піти на додаткову складність використання getopts.

В якості швидкої довідки мені подобається 60-секундний підручник з getopts .

Ви також можете розглянути getoptпрограму замість вбудованої оболонки getopts. Це дозволяє використовувати довгі параметри та параметри після аргументів, які не є варіантами (наприклад, foo a b c --verboseа не просто foo -v a b c). Ця відповідь Stackoverflow пояснює, як користуватися GNU getopt.

jeffbyrnes згадав, що оригінальне посилання загинуло, але, на щастя, так, як машина його архівувала.


Дякую! Я із задоволенням використовую getopts вже рік, але також буду дивитись на getopt.
tttppp

1
На жаль, посилання на 60-й підручник з getopts мертве; здається, що bashcurescancer.com вже не є. Ось посилання на версію машини Wayback Machine .
jeffbyrnes


Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.