Ao executar um shell script, é possível passar parâmetros posicionais específicos sem precisar inseri-los todos em ordem?

13

Por exemplo, se eu tiver o script ./foo que usa 10 parâmetros e eu quero apenas passar o 8º parâmetro. A única maneira de saber como fazer isso atualmente é:

./foo '' '' '' '' '' '' '' 'bar'

Existe uma maneira mais fácil / melhor?

Kerry Randolph
fonte
1
É por isso que os programas geralmente usam opções em vez de parâmetros posicionais, se você tiver muitos parâmetros.
Barmar 10/09/14

Respostas:

4

Outra maneira de fazer isso é nomear o parâmetro que você deseja declarar e, em seguida, fazê-lo:

{   cat >./foo 
    chmod +x ./foo
    eight=declared ./foo
    eight=declared_and_preferred \
        ./foo 1 2 3 4 5 6 7 8
    ./foo 1 2 3 4 5 6 7 8
    ./foo
} <<\SCRIPT
#!/usr/bin/sh
: ${eight:=${8:-some_default}}
printf '$eight = %s\n' "$eight"
#END
SCRIPT

RESULTADO

$eight = declared
$eight = declared_and_preferred
$eight = 8
$eight = some_default

No exemplo acima, a variável de ambiente declarada explicitamente é preferida ao argumento da linha de comandos, mas o argumento da linha de comandos é usado quando a variável de ambiente está vazia ou não está definida. Quando a oitava posição e a variável de ambiente $eightestiverem vazias ou desabilitadas, o valor padrão a que algum padrão é atribuído $eight. Em ambos os casos, :pode ser removido das instruções :-ou :=se vazio deve ser um valor aceitável.

A variável também $eightpoderia ter sido definida como:

printf '$eight = %s\n' "${eight:=${8:-some_default}}"

... e a linha anterior foi totalmente omitida, mas eu queria demonstrar que declarar uma variável dessa maneira resulta em um valor persistente, e por isso fiz isso em dois comandos. De qualquer maneira, $eighté definido o valor final dessa expansão de parâmetro composto.

getopts- para scripts robustos - geralmente é a melhor maneira de lidar com opções de comando . Parâmetros posicionais, por outro lado, são quase sempre os meios mais simples de manipular robustos operandos em um script.

Por exemplo:

touch file$(seq -ws\ file 100)
./foo *

RESULTADO

$eight = file008

Lá vemos apenas o oitavo operando, mas existem 101 deles no meu diretório de teste.

mikeserv
fonte
18

Supondo que você possa alterar o script, considere usar parâmetros opcionais (opções) em vez de parâmetros obrigatórios (argumentos).

Se você tiver cada um dos 7 primeiros sete parâmetros como opções e tiver como padrão a sequência vazia, poderá fazer o seguinte:

./foo bar

Se você usa um shell compatível com POSIX, pode usar o getoptsutilitário ou o programa getopt. bash- como a maioria das conchas - oferece getoptscomo um built-in. De qualquer maneira, é mais fácil do que rolar seu próprio analisador de linha de comando.

A menos que você implemente algo como os últimos argumentos não opcionais X, os valores dos últimos argumentos Y e XY são obrigatórios. No entanto, isso não é uma prática comum, normalmente uma opção é sempre uma opção e um argumento é um argumento, e a ordem da opção "inserção" é gratuita.

Anthon
fonte
5
+1para getopt(s). Os parâmetros posicionais são um momento triste e devem ser evitados.
precisa saber é o seguinte