Por que este case não funciona no Ubuntu?

1

Estou mudando do BSD para o Linux. Script no Ubuntu 16.04

#!/bin/sh
while (( "$#" )); do
   case "$1" in
    -i | --ignore-case)
        [ $# -ne 2 ] && echo "2 arguments i needed" && exit 1
        case_option=-i
        ;;
    -*)
        echo "Error: Unknown option: $1" >&2
        exit 1
        ;;
     *) # No more options
        break
        ;;
   esac

   shift
done

# -o, if not, then ...
find $HOME ! -readable -prune -o \
    -type f -name "*.tex" -exec grep -l $case_option "$1" {} + | vim -R -

O erro está em loop.

  • sh ./script masi retorna a mesma saída que a saída esperada.
  • Executar sh ./script -i masi . Saída: arquivo em branco. Saída esperada: lista de resultados. STOUT é ./script: 2: ./script: 2: not found Vim: Reading from stdin... .

Possíveis erros

  • while (( "$#" ))
  • ...

Não consigo usar as opções por algum motivo.

Mudando para getopts - motivação pela resposta de terdon

Tutorial e responda aqui

case_option=""

while getopts "i:" opt; do
    case $opt in
        i | ignore_case) 
            [[ $# -ne 2 ] && echo "2 arguments i needed" && exit 1
            case_option=-i
            ;;
        -*)
            echo "Error: Unknown option: $1" >&2
            exit 1
            ;;
        *) # No more options 
           break
           ;;
    esac
done

find $HOME ! -readable -prune -o \
   -type f -name "*.tex" -exec grep -l $case_option "$1" {} + | vim -R -

onde

  • chamando por ./script masi ou ./script -i masi .

Como você pode fazer casos em while loop?

    
por Léo Léopold Hertz 준영 02.06.2016 / 15:54

3 respostas

0

Aqui estão dois exemplos de processamento de opções, primeiro com o shell getopts embutido e, em seguida, com getopt de util-linux .

getopts não suporta --long opções, apenas opções curtas.

getopt suporta ambos. Se você quiser usar getopt , use SOMENTE a versão do pacote util-linux . NÃO use qualquer outra versão do getopt, eles estão todos quebrados e inseguros de usar, util-linux ' getopt é o único que funciona.

Felizmente, no Linux, a versão util-linux é a única versão que você provavelmente terá, a menos que você se divirta para instalar uma versão quebrada.

getopts é mais portátil (funciona na maioria dos descendentes de bourne-shell) e faz mais por você automaticamente (por exemplo, menos configuração é necessária e você não precisa executar shift ou shift 2 para cada opção , dependendo se a opção aceita um argumento ou não), mas é menos capaz (não suporta opções longas).

De qualquer forma, além de processar a opção -i ( --ignore-case ), adicionei uma opção -h ( --help ) e um exemplo de uma opção que requer um argumento -x ( --example ). Não faz nada útil, só está aí para mostrar como fazer isso.

Com getopts , o código é:

#! /bin/bash

usage() {
# a function that prints an optional error message and some help.
# and then exits with exit code 1
[ -n "$*" ] && printf "%s\n" "$*" > /dev/stderr

cat <<__EOF__
Usage:
      $0 [-h] [ -i ] [ -x example_data ]

-i    Ignore case
-x    The example option, requires an argument.
-h     This help message.

Detailed help message here
__EOF__

exit 1
}

case_option=''
case_example=''

while getopts "hix:" opt; do
    case "$opt" in
        h) usage ;;
        i) case_option='-i' ;;
        x) case_example="$OPTARG" ;;
        *) usage ;;
    esac
done
shift $((OPTIND-1))

find "$HOME" ! -readable -prune -o -type f -name "*.tex" \
    -exec grep -l ${case_option:+"$case_option"} "$1" {} + |
    vim -R -

Com getopt de util-linux :

#! /bin/bash

usage() {
# a function that prints an optional error message and some help.
# and then exits with exit code 1
[ -n "$*" ] && printf "%s\n" "$*" > /dev/stderr

cat <<__EOF__
Usage:
      $0 [ -h ] [ -i ] [ -x example_data ]
      $0 [ --help ] [ --ignore-case ] [ --example example_data ]

-i, --ignore-case    Ignore case
-x, --example        The example option, requires an argument.
-h, --help           This help message

Detailed help message here
__EOF__

exit 1
}

case_option=''
case_example=''

# getopt is only safe if GETOPT_COMPATIBLE is not set.
unset GETOPT_COMPATIBLE

# POSIXLY_CORRECT disables getopt parameter shuffling, so nuke it.
# parameter shuffling moves all non-option args to the end, after
# all the option args.  e.g. args like "-x -y file1 file2 file3 -o optval"
# become "-x -y -o optval -- file1 file2 file3"
unset POSIXLY_CORRECT

OPTS_SHORT='hix:'
OPTS_LONG='help,ignore-case,example:'
# check options and shuffle them
TEMP=$(getopt -o "$OPTS_SHORT" --long "$OPTS_LONG" -n "$0" -- "$@")

if [ $? != 0 ] ; then usage ; fi

# assign the re-ordered options & args to this shell instance
eval set -- "$TEMP"

while true ; do
  case "$1" in
    -i|--ign*) case_option='-i' ; shift ;;
    -x|--exa*) case_example="$2" ; shift 2 ;;

    -h|--hel*) usage ;;

    --) shift ; break ;;
     *) usage ;;
  esac
done

find "$HOME" ! -readable -prune -o -type f -name "*.tex" \
    -exec grep -l ${case_option:+"$case_option"} "$1" {} + |
    vim -R -
    
por 03.06.2016 / 03:48
4

Ele está falhando porque você o está executando usando dash e não sh ou bash . No Ubuntu, /bin/sh é um link simbólico para /bin/dash , um shell mínimo compatível com POSIX. A solução mais simples é executar seu script com bash , onde ele funcionará como esperado:

bash ./script masi

Além disso, observe que você tem uma linha shebang:

#!/bin/sh

O que significa que você não precisa executar sh ./script , você pode simplesmente fazer ./script . Basta alterar a linha shebang para apontar para bash em vez de sh :

#/bin/bash

Se você insistir em usar sh ( dash no Ubuntu), precisará alterar o while do loop para:

while [ "$#" -gt 0 ]; do

Como alternativa, convém consultar getopts .

    
por 02.06.2016 / 16:24
1

getopts lida com argumentos de opção, o que seu script não funciona.

Aqui está um pequeno quadro funcional:

case_option="" 

while getopts "i:" opt; do 
    case $opt in 
        'i') 
                I_ARG=$OPTARG 
                ;; 
        '?') 
                exit 1 
                ;;  
    esac 
done
shift $(($OPTIND - 1)) 
echo $@ 
    
por 03.06.2016 / 15:10