Включая подпараметры в опциях справки выполниться мудро без getopt или getopts?

Предположение, что Вы используете Единицу....

  1. Нажмите значок Setting/Power на верхнее правое.
  2. Нажмите "System Settings".
  3. Когда окно откроется, нажмите "Brightness and Lock"
  4. Корректируйтесь, "Выключают экран, когда неактивный для" к Вашей симпатии.

Screenshort

3
04.05.2013, 17:08
3 ответа

Это - версия, которая более удобна для использования, чем первый, который я дал здесь, в особенности он избегает дублированного кода для эквивалентных долгих и коротких опций. Это должно обработать что-либо, что Вы когда-либо хотите для опций: короткие опции (-q), долгие опции (--quiet), опции с аргументами, накопленные короткие опции (-qlfinput вместо -q -l -f input), исключительно сокращаемые долгие опции (--qui вместо --quiet), конец опций --.

Большая часть кода исправлена; только необходимо изменить отмеченные части.

#!/bin/bash

# Update USAGE (USAGE1, USAGE2, USAGE3 may remain unchanged):
USAGE='Usage: prog [-q|--quiet] [-l|--list] [-f file|--file file] [-Q arg|--query arg] args'
USAGE1='
Ambiguously abbreviated long option:'
USAGE2='
No such option:'
USAGE3='
Missing argument for'

# List all long options here (including leading --):
LONGOPTS=(--quiet --list --file --query)

# List all short options that take an option argument here
# (without separator, without leading -):
SHORTARGOPTS=fQ

while [[ $# -ne 0 ]] ; do
  # This part remains unchanged
  case $1 in
  --) shift ; break ;;  ### no more options
  -)  break ;;          ### no more options
  -*) ARG=$1 ; shift ;;
  *)  break ;;          ### no more options
  esac

  # This part remains unchanged
  case $ARG in
  --*)
    FOUND=0
    for I in "${LONGOPTS[@]}" ; do
      case $I in
      "$ARG")  FOUND=1 ; OPT=$I ; break ;;
      "$ARG"*) (( FOUND++ )) ; OPT=$I ;;
      esac
    done
    case $FOUND in
    0) echo "$USAGE$USAGE2 $ARG" 1>&2 ; exit 1 ;;
    1) ;;
    *) echo "$USAGE$USAGE1 $ARG" 1>&2 ; exit 1 ;;
    esac ;;
  -["$SHORTARGOPTS"]?*)
    OPT=${ARG:0:2}
    set dummy "${ARG:2}" "$@"
    shift ;;
  -?-*)
    echo "$USAGE" 1>&2 ; exit 1 ;;
  -??*)
    OPT=${ARG:0:2}
    set dummy -"${ARG:2}" "$@"
    shift ;;
  -?)
    OPT=$ARG ;;
  *)
    echo "OOPS, this can't happen" 1>&2 ; exit 1 ;;
  esac

  # Give both short and long form here.
  # Note: If the option takes an option argument, it it found in $1.
  # Copy the argument somewhere and shift afterwards!
  case $OPT in
  -q|--quiet) QUIETMODE=yes ;;
  -l|--list)  LISTMODE=yes ;;
  -f|--file)  [[ $# -eq 0 ]] && { echo "$USAGE$USAGE3 $OPT" 1>&2 ; exit 1 ; }
              FILE=$1 ; shift ;;
  -Q|--query) [[ $# -eq 0 ]] && { echo "$USAGE$USAGE3 $OPT" 1>&2 ; exit 1 ; }
              QUERYARG=$1 ; shift ;;
  *)          echo "$USAGE$USAGE2 $OPT" 1>&2 ; exit 1 ;;
  esac
done

# Remaining arguments are now in "$@":

echo "QUIETMODE = $QUIETMODE"
echo "LISTMODE = $LISTMODE"
echo "FILE = $FILE"
echo "QUERYARG = $QUERYARG"
echo "REMAINING ARGUMENTS:" "$@"
3
27.01.2020, 21:14
  • 1
    Привет @Uwe, я попробовал этот код. Хотя логика выглядит корректной, я не могу видеть любой вывод. Можно ли совместно использовать демонстрационный вывод для вышеупомянутого кода? –  San 06.05.2013, 11:48
  • 2
    prog --que 123 -l 456 урожаи QUIETMODE = \n LISTMODE = yes\n ФАЙЛ = \n QUERYARG = 123\n ОСТАЮЩИЕСЯ АРГУМЕНТЫ: 456 (идентичный вывод для удара 3.2.39 и 4.1.5) –  Uwe 06.05.2013, 11:59
  • 3
    Благодарит тонну! Это работает теперь. Этот сценарий похож супер усовершенствованный показанный. Спасибо еще раз @Uwe :-) –  San 06.05.2013, 12:30

КАВЫЧКА. Всегда кавычка. Когда в сомнении; кавычка. Если не в сомнении; кавычка.

Например: Ваш тест на $1, (который никогда не достигается из-за exit), разрушил бы Ваш сценарий, если названо с, например. ./myscript "file name with spaces".


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

#!/bin/bash

prnt_help()
{
    printf "Usage: %s [OPTION]\n" $(basename "$1")
}

# A simple function only to visualize what gets passed and one of many
# ways to deal with it.
do_list()
{
    printf "do_list:\n"
    printf "OPT: %s\n" "$@"
    printf "My list:\n"
    while [[ -n "$1" && "${1:0:1}" != "-" ]]; do
        printf "Processing %s\n" "$1"
        shift
    done
}

main()
{
    while [[ -n "$1" ]];do
           # This test is not needed, but include it if you find use for it.
        if [[ "${1:0:1}" != "-" ]]; then
            shift
            continue
        fi
        # Check option and pass rest of arguments to matching function
        printf "Checking option %s\n" "$1"
        case "$1" in
        "-l"|"--list") shift; do_list "$@";;
        "-h"|"--help") prnt_help "$0";;
        "--") printf "Rest is not options even if starts with -\n"
            break;;
        esac
        shift
    done
    # If you use "--" to separate out e.g. filenames starting with -
    # then process them here.
}

main "$@"
2
27.01.2020, 21:14
  • 1
    И кроме того "ЗАКЛЮЧИТЬ В КАВЫЧКИ": Присвоение массива $@ к простой переменной options и затем цикличное выполнение $options также плохая идея, так как Вы больше не можете различать пространство в аргументе и пространство между аргументами. Использовать for argument in "$@" ; do вместо этого (и снова: отметьте кавычки!) –  Uwe 04.05.2013, 11:44

Встроенный ГУМКТЫ Только разбирается только короткие варианты (кроме KSH93), Но вы все равно можете добавить несколько строк сценариев, чтобы сделать Getopts обрабатывает длинные варианты.

Вот часть кода, найденной в http://www.uxora.com/unix/shell-script/22-handle-long-scriptions-with-getopts

  #== set short options ==#
SCRIPT_OPTS=':fbF:B:-:h'
  #== set long options associated with short one ==#
typeset -A ARRAY_OPTS
ARRAY_OPTS=(
    [foo]=f
    [bar]=b
    [foobar]=F
    [barfoo]=B
    [help]=h
    [man]=h
)

  #== parse options ==#
while getopts ${SCRIPT_OPTS} OPTION ; do
    #== translate long options to short ==#
    if [[ "x$OPTION" == "x-" ]]; then
        LONG_OPTION=$OPTARG
        LONG_OPTARG=$(echo $LONG_OPTION | grep "=" | cut -d'=' -f2)
        LONG_OPTIND=-1
        [[ "x$LONG_OPTARG" = "x" ]] && LONG_OPTIND=$OPTIND || LONG_OPTION=$(echo $OPTARG | cut -d'=' -f1)
        [[ $LONG_OPTIND -ne -1 ]] && eval LONG_OPTARG="\$$LONG_OPTIND"
        OPTION=${ARRAY_OPTS[$LONG_OPTION]}
        [[ "x$OPTION" = "x" ]] &&  OPTION="?" OPTARG="-$LONG_OPTION"

        if [[ $( echo "${SCRIPT_OPTS}" | grep -c "${OPTION}:" ) -eq 1 ]]; then
            if [[ "x${LONG_OPTARG}" = "x" ]] || [[ "${LONG_OPTARG}" = -* ]]; then 
                OPTION=":" OPTARG="-$LONG_OPTION"
            else
                OPTARG="$LONG_OPTARG";
                if [[ $LONG_OPTIND -ne -1 ]]; then
                    [[ $OPTIND -le $Optnum ]] && OPTIND=$(( $OPTIND+1 ))
                    shift $OPTIND
                    OPTIND=1
                fi
            fi
        fi
    fi

    #== discard option argument start with hyphen ==#
    if [[ "x${OPTION}" != "x:" ]] && [[ "x${OPTION}" != "x?" ]] && [[ "${OPTARG}" = -* ]]; then 
        OPTARG="$OPTION" OPTION=":"
    fi

    #== manage options ==#
    case "$OPTION" in
        f  ) foo=1 bar=0                    ;;
        b  ) foo=0 bar=1                    ;;
        B  ) barfoo=${OPTARG}               ;;
        F  ) foobar=1 && foobar_name=${OPTARG} ;;
        h ) usagefull && exit 0 ;;
        : ) echo "${SCRIPT_NAME}: -$OPTARG: option requires an argument" >&2 && usage >&2 && exit 99 ;;
        ? ) echo "${SCRIPT_NAME}: -$OPTARG: unknown option" >&2 && usage >&2 && exit 99 ;;
    esac
done
shift $((${OPTIND} - 1))

Вот тест:

# Short options test
$ ./foobar_any_getopts.sh -bF "Hello world" -B 6 file1 file2
foo=0 bar=1
barfoo=6
foobar=1 foobar_name=Hello world
files=file1 file2

# Long and short options test
$ ./foobar_any_getopts.sh --bar -F Hello --barfoo 6 file1 file2
foo=0 bar=1
barfoo=6
foobar=1 foobar_name=Hello
files=file1 file2

В противном случае в последнее время Korn Shell KSH93, Getopts может естественным образом проанализировать длинные варианты и даже отображать страницу человека. (См. http://www.uxora.com/unix/shell-script/20-getopts-with-man-page-and-long-options ).

1
27.01.2020, 21:14

Теги

Похожие вопросы