A variável numérica do argumento não conta os parâmetros inseridos [duplicados]

3

Eu tenho o seguinte script:

echo  'Please select type file , the name of the input file and the name of the output file:

     a.plain ( please press a ) <input_file> <output_file>;
     b.complex ( please press b ) <input_file> <output_file>;'

read one two three
echo $#

if  [ $# -ne 3 ]; then
   echo "Insufficient arguments !"
   exit 1;
else
   echo "Number of passed parameters is ok"
fi

$# sempre gera 0, o comando de leitura fornece as variáveis corretas quando estou usando $ one, $ dois e $ três depois no script

Obrigado.

    
por bboy 23.11.2018 / 08:48

3 respostas

7

Para testar se você obteve valores para todas as variáveis e sair do contrário, use o teste -z para testar strings vazias:

if [ -z "$one" ] || [ -z "$two" ] || [ -z "$three" ]; then
    echo 'Did not get three values' >&2
    exit 1
fi

O valor $# é o número de parâmetros posicionais , geralmente argumentos de linha de comando (ou valores definidos pelo set builtin). Eles estão disponíveis em $1 , $2 , $3 , etc. (ou coletivamente na matriz "$@" ) e não estão relacionados aos valores lidos pelo read construído.

Para fazer com que seu script tome a entrada como argumentos de linha de comando em vez de lê-los interativamente (o que pode ser preferido se o usuário fornecer um ou vários caminhos, pois eles podem tirar proveito da conclusão de tabulação) para usar o script de outro script e não requer que haja um terminal conectado), use

if [ "$#" -ne 3 ]; then
    echo 'Did not get three command line arguments' >&2
    exit 1
fi

one=$1
two=$2
three=$3

O script, nesse caso, seria executado como

./script.sh a.plain /path/to/inputfile /path/to/outputfile

Se o processamento da entrada puder acontecer a partir da entrada padrão e se a saída puder ser enviada para a saída padrão (ou seja, se você não precisar os caminhos explícitos do arquivo de entrada e do arquivo de saída dentro do script), o script só precisa receber o primeiro parâmetro ( a.plain ou b.complex ).

./script.sh a.plain </path/to/inputfile >/path/to/outputfile

O script então usaria a entrada padrão e os fluxos de saída padrão para entrada e saída (e consequentemente só precisa verificar um argumento de linha de comando único ).

Isso tornaria possível executar o script com dados enviados de outro programa e também permitiria mais pós-processamento:

gzip -dc <file-in.gz | ./script.sh a.plain | sort | gzip -c >file-out.gz
    
por 23.11.2018 / 09:13
4

O que você está fazendo errado

Você está confundindo os argumentos de entrada (para o script, na inicialização) e a entrada do usuário, usando a leitura (no tempo de execução).

$# informa o número de argumentos na inicialização. por exemplo. para ./«script_name» 1 2 3 , quando usado no script, ele retornará 3.

    
por 23.11.2018 / 08:59
0

Você pode usar o comando set para redefinir os argumentos posicionais, sobrescrevendo os valores anteriores. A variável IFS especifica a lista de caracteres a serem usados como um separador, portanto, você também pode usar isso para analisar o CSV. Observe que set é interno, portanto, a sintaxe usual para substituir variáveis para comandos únicos não funciona, pois as variáveis especificadas antes de um comando são uma abreviação do comando env , que definiria o ambiente para um subprocesso.

$# é o número de argumentos posicionais que existem atualmente.

$ read foo
a b c d e      
$ echo $foo
a b c d e
$ set -- $foo
$ echo $#
5
$ IFS=: set -- $foo                  # doesn't work
$ echo $#
5                                    # still got 5
$ IFS=:
$ set -- $foo
$ echo $#
1
    
por 23.11.2018 / 16:08