Разбор getopts в bash

У меня есть функция bash, с которой я пытаюсь использовать getopts, и у меня возникают проблемы.

Функция предназначена для вызова сама по себе (getch), с необязательным флагом -s (getch -s) или с необязательным строковым аргументом после (поэтому getch master и getch -s master оба допустимы).

Фрагмент ниже - это то, в чем заключается моя проблема - это не вся функция, но это то, на чем я сосредоточен:

getch()
{
  if [ "$#" -gt 2 ] || [ "$1" = "-h" ] || [ "$1" = "--help" ]; then
    echo "Usage: $0 [-s] [branch-name]" >&2
    return 1
  fi

  while getopts "s" opt; do
    echo $opt # This line is here to test how many times we go through the loop
    case $opt in
      s) 
        squash=true
        shift
        ;;
      *) 
        ;;
    esac
  done
}

В случае getch -s master происходит странность. Приведенное выше должно выдать s один раз, но вместо этого я получаю следующее:

[user@host:git-repositories/temp]$ getch -s master
s
s
[user@host:git-repositories/temp]$

Почему он дважды анализирует параметр -s?


person ABach    schedule 21.05.2010    source источник
comment
Мне трудно воспроизвести эту проблему. Я скопировал ваш код в файл и запустил его с помощью -s master, -s -s -s и любых других глупостей, и я не могу получить более 1 с для печати.   -  person Daniel Harms    schedule 22.05.2010
comment
Извините, я тоже не могу воспроизвести. Он отлично работает для меня. Измените свой echo $opt на echo "In getopts: $opt", чтобы он отличался на случай, если что-то еще повторит его.   -  person Dennis Williamson    schedule 22.05.2010
comment
Поместите OPTIND=1 перед циклом getops. $OPTIND - это позиция в списке параметров, которая должна быть проанализирована getopts следующей (когда вы закончите цикл while, вы должны сделать shift $((OPTIND-1)), чтобы сместить эти проанализированные параметры). Если вы не установите OPTIND в 1, в следующий раз, когда вы будете выполнять getopts в текущей оболочке (например, в другой функции), вы будете анализировать, начиная с параметра $OPTIND-th, обычно пустого, заставляя getops возвращать false, а в то время как выходит сразу, без разбора параметров.   -  person Olivier Dulac    schedule 03.12.2012
comment
и не shift внутри цикла getops. Вместо этого после done поместите shift $((OPTIND -1)), чтобы сместить все параметры, проанализированные getopts.   -  person Olivier Dulac    schedule 03.12.2012


Ответы (3)


Я также не могу воспроизвести проблему на компьютере с Ubuntu 10.4, на котором работает Bash 4, или на моем компьютере MacOSX, на котором работает Bash 3.2.17.

Ваша среда оболочки может быть испорчена предыдущими усилиями по отладке.

Вы пытались начать с нового окна терминала? Или запустите новую оболочку с помощью «exec bash» и повторите попытку.

stefanl@ubuntu:~ $ getch()
> {
>   if [ "$#" -gt 2 ] || [ "$1" = "-h" ] || [ "$1" = "--help" ]; then
>     echo "Usage: $0 [-s] [branch-name]" >&2
>     return 1
>   fi
> 
>   while getopts "s" opt; do
>     echo $opt # This line is here to test how many times we go through the loop
>     case $opt in
>       s) 
>         squash=true
>         shift
>         ;;
>       *) 
>         ;;
>     esac
>   done
> }
stefanl@ubuntu:~ $ getch -s master
s
person Stefan Lasiewski    schedule 21.05.2010
comment
Я попытался сделать новую подоболочку, как вы предложили, и это сработало. Должно быть, что-то сделали с моей средой заранее... В любом случае, спасибо за помощь! - person ABach; 23.05.2010
comment
Это случается время от времени. Легко застрять на отладке скрипта и забыть, что ваша среда может быть повреждена. - person Stefan Lasiewski; 24.05.2010
comment
(удаление комментариев, которые я ошибочно разместил в этом ответе, а не в сообщении спрашивающего) - person Olivier Dulac; 03.12.2012

Вот способ сделать это без getopts:

http://bsdpants.blogspot.com/2007/02/option-ize-your-shell-scripts.html

person yabt    schedule 22.05.2010

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

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

person Daniel Harms    schedule 22.05.2010