É possível usar variáveis ​​de parâmetro do shell ($ 1,…, $ @) diretamente na CLI?

9

Às vezes, é necessário emular e verificar as variáveis ​​acima em pequenos exemplos e, em seguida, pode ser copiado imediatamente para algum script, etc.

Tentei resolver usando um exemplo simples das seguintes maneiras:

(find $1) /tmp
sh -c '(find $1) /tmp'
sh -c "find $1" /tmp
echo '(find $1) /tmp' | sh

e com outras combinações. Também experimentei adicionando a diretiva de intérprete shebang #!/bin/sh -x, mas não obteve o resultado desejado.

Posso fazer isso simplesmente?

Apóstolo
fonte
1
(find $1) /tmpé um erro de sintaxe. Na verdade, (any-command) more-argumentsé um erro de sintaxe. Você pode explicar de maneira diferente o que está tentando fazer?
Celada
2
@Celada, não é um erro de sintaxe em conchas da rcfamília ( rc, es, akanga...), onde, nesse caso, que é equivalente a find $1 /tmp.
Stéphane Chazelas

Respostas:

15

O primeiro argumento depois sh -c inline-scriptvai para $0(que também é usado para mensagens de erro) e o restante entra $1, $2...

$ sh -c 'blah; echo "$0"; echo "$1"' my-inline-script arg
my-inline-script: blah: command not found
my-inline-script
arg

Então você quer:

sh -c 'find "$1"' sh /tmp

(antigamente, era possível encontrar shimplementações em que o primeiro argumento foi feito $1, então você faria:

sh -c 'find "$1"' /tmp /tmp

Ou:

sh -c 'shift "$2"; find "$@"' sh 3 2 /tmp1 /tmp2

para explicar os dois comportamentos, mas essas conchas se foram agora que o POSIX é predominante e está disponível publicamente).


Se você deseja definir $1, $2em um escopo local no shell atual, é onde você usaria funções. Em conchas tipo Bourne:

my_func() {
  find "$1"
}
my_func /tmp

Alguns shells suportam funções anônimas. Esse é o caso de zsh:

(){find "$1"} /tmp

Ou es:

@{find $1} /tmp

Para alterar os parâmetros posicionais atuais, permanentemente, a sintaxe depende do shell. dchirikov já cobriu o Bourne-como conchas (Bourne, Korn, bash, zsh, POSIX, ash, yash...).

A sintaxe é:

set arg1 arg2 ... argn

No entanto, você precisa de:

set --

Para esvaziar essa lista (ou shift "$#") e

set -- -foo

para definir $1algo que comece com -ou +, por isso é um bom hábito sempre usar set --especialmente ao usar dados arbitrários, como set -- "$@" other-argadicionar argumentos ao final da lista de parâmetros posicionais.

Nas conchas da cshfamília ( csh, tcsh), você atribui à argvmatriz:

set argv=(arg1 arg2)

Em conchas da rcfamília ( rc, es, akanga), para a *matriz:

*=(arg1 arg2)

Embora você também possa atribuir elementos individualmente:

2=arg2

Em fish, os parâmetros de posição são na argvmatriz única (não $1, $@lá):

set argv arg1 arg2

Em zsh, para compatibilidade com csh, você também pode atribuir à argvmatriz:

argv=(arg1 arg2)
argv[4]=arg4

E você também pode fazer:

5=arg5

Isso significa que você também pode fazer coisas como:

argv+=(another-arg)

para adicionar um argumento ao final e:

argv[-1]=()
argv[2]=()

para remover um argumento do final ou do meio, o que você não pode fazer facilmente com outras conchas.

Stéphane Chazelas
fonte
7
set --

é o que você precisa:

$ set -- aaa bbb ccc
$ echo "$1"
aaa
$ echo "$2"
bbb
$ echo "$3"
ccc
$ echo "$@"
aaa bbb ccc
dchirikov
fonte