Por que $ # é sempre 0 na minha função?

5

Bash está me deixando louca. Não consigo entender por que o seguinte (nem algumas das dezenas de variações que copiei e colei literalmente dos exemplos) não funciona:

#!/bin/bash

echo $#

function main {
    if (( $# < 1 )); then
        usage
    fi

    echo "good"
}

function usage {
    echo "Usage: $0 <outputdir>"
    exit 1
}

main

Por alguma razão, a verificação de argumentos falha toda vez, mesmo quando eu passo um argumento e posso ver claramente que $# está definido como esperado.

    
por devios1 16.07.2013 / 23:59

2 respostas

10

Você está chamando a função main sem argumento. Então, $# na função principal é sempre 0.

Cada instância da função possui seus próprios argumentos. (“Instância” significa que se a função for iniciada várias vezes (por meio de chamadas recursivas), cada chamada terá seus próprios argumentos.) Os parâmetros posicionais $1 , $2 , etc., bem como os parâmetros associados $# , $* e $@ referem-se aos argumentos passados na chamada de função. Por exemplo, se você chamar main foo bar , dentro da função main , o valor de $1 será foo , o valor de $# será 2 e assim por diante.

Se você quiser passar os argumentos do script para uma função, use "$@" . Essa construção se expande para a lista de argumentos passados para o script (ou para a função, se chamada dentro de uma função). Observe que, diferentemente do que acontece normalmente com aspas duplas, os parâmetros são transmitidos separadamente, "$@" é uma lista de strings e não uma única string. As aspas duplas são necessárias, caso contrário, os parâmetros não serão transmitidos como estão, mas serão tratados como uma lista separada por espaço em branco de padrões de nome de arquivo.

function main {
  if (( $# < 1 )); then
    usage
  fi
  echo "good"
}
main "$@"
    
por 17.07.2013 / 03:31
7

Isso deve funcionar:

#!/bin/bash
set -x
NARGS=$#

function main {
    if [ $NARGS -lt 1 ]; then
        usage
    fi

    echo good
}

function usage {
    echo "Usage: $0 <outputdir>"
    exit 1
}

main

Eu deixei o set -x de propósito. É útil depurar esses erros. Se você não passar nenhum argumento para a função main , $# ficará 0 dentro dele (substitua $NARGS por $# na condição if para ver isso).

    
por 17.07.2013 / 01:46