usando 'case $1 in' para ler opções de comando - vários sinalizadores após traço e manipular sinalizadores incomuns?

usando 'case $1 in' para ler opções de comando - vários sinalizadores após traço e manipular sinalizadores incomuns?

Estou criando um script bash que usa opções longas e sinalizadores curtos. Como quero opções longas, não posso usar getopts. Tentei usar o seguinte código:

while test -n "$1"; do
  case "$1" in
        -o|--override)  NO_CHANGE=yes;shift 1;;
        -r|--reset)     OV_RESET=yes;shift 1;;
        -h|--help)      hthemehelp;shift 1;;
        *)              break;;
  esac
done

Isso funciona quando eu o invoco como myscr -o -rou myscr -h, mas quando tento myscr -oro programa simplesmente executa seu comportamento normal, e executá myscr -or -h-lo sai do loop antes de chegar a -h. Substituir breakpor continuecausas justas myscr -ore myscr -or -htravar.

Responder1

Experimente isto para ver o tamanho:

#!/bin/bash
pleasereset=1
while test -n "$1"; do
   pleaseshift=0
   [[ pleasereset -eq 1 ]] && thisvar=$1 && pleasereset=0;
   case "$thisvar" in
      -o*|--override) echo "override!"; pleaseshift=1;;
      -r*|--reset) echo "reset!"; pleaseshift=1;;
      -h*|--help) echo "help!"; pleaseshift=1;;
      *) break ;;
   esac
   if [[ "$pleaseshift" = "1" ]];
   then
      testvar=${thisvar##-}
      if [[ ${#testvar} -gt 1 ]] && [[ ! ${thisvar} = --* ]];
      then
         thisvar=-$( echo "$testvar" | cut -c 2- )
      else
         shift 1; pleasereset=1;
      fi
   fi
done

Observe que no primeiro parâmetro que não corresponde a nenhum caso específico, a análise do parâmetro será interrompida, portanto, a ./foobar.sh -o --help -s -rnão processará o arquivo -r. Isso pode ser ajustado alterando a *) break;;linha para tratamento de erros, mas lembre-se de colocar o pleaseshift=1!

Responder2

Talvez seja suficiente adicionar a linha que você deseja:

while test -n "$1"; do
  case "$1" in
        -or|-ro)        OV_RESET=yes;NO_CHANGE=yes;shift 1;;
        -o|--override)  NO_CHANGE=yes;shift 1;;
        -r|--reset)     OV_RESET=yes;shift 1;;
        -h|--help)      hthemehelp;shift 1;;
        *)              break;;
  esac
done

ou, mais complexo, você pode colocar o casebloco em uma função com o shift 1out desse bloco, mas ainda dentro do while.
Para odobrouopções ( -or, -oh, que não são longas, você pode chamar recursivamente a mesma função para cada letra de case *)... Você precisa de um sinalizador se acabou de processar $1como uma opção longa. Nesse caso, entretanto, você expõe seu script tp mau comportamento devido a erro de impressão (por exemplo, se eu escrever -overrider I will process-o -v -e -r -d`...)

informação relacionada