Czy można używać zmiennych parametrów powłoki ($ 1,…, $ @) bezpośrednio w CLI?

9

Czasami konieczna jest emulacja i weryfikacja powyższych zmiennych w małych przykładach, a następnie można je natychmiast skopiować do jakiegoś skryptu itp.

Próbowałem rozwiązać, używając prostego przykładu na następujące sposoby:

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

i z innymi kombinacjami. Eksperymentowałem również, dodając dyrektywę interpretera shebang #!/bin/sh -x, ale nie uzyskałem pożądanego rezultatu.

Czy mogę to zrobić po prostu?

Apostoł
źródło
1
(find $1) /tmpjest błędem składni. W rzeczywistości (any-command) more-argumentsjest to błąd składniowy. Czy potrafisz inaczej wytłumaczyć, co próbujesz zrobić?
Celada
2
@Celada, to nie jest błąd składni w muszli z rcrodziną ( rc, es, akanga...), przy czym w tym przypadku, który jest odpowiednikiem find $1 /tmp.
Stéphane Chazelas

Odpowiedzi:

15

Pierwszy argument po sh -c inline-scriptidzie $0(który jest również stosowany do komunikatów o błędach), a reszta iść $1, $2...

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

Więc chcesz:

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

(w dawnych czasach można było znaleźć shimplementacje, w które wszedł pierwszy argument $1, więc zrobiłbyś:

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

Lub:

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

aby uwzględnić oba zachowania, ale te powłoki zniknęły teraz, gdy POSIX jest powszechny i ​​publicznie dostępny).


Jeśli chcesz ustawić $1, $2w zakresie lokalnym w bieżącej powłoce, to właśnie tam możesz użyć funkcji. W muszlach podobnych do Bourne'a:

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

Niektóre powłoki obsługują anonimowe funkcje. Tak jest w przypadku zsh:

(){find "$1"} /tmp

Lub es:

@{find $1} /tmp

Aby trwale zmienić bieżące parametry pozycyjne, składnia zależy od powłoki. dchirikov już pokryte Bourne-jak muszli (Bourne, Korn bash, zshPOSIX, ash, yash...).

Składnia jest następująca:

set arg1 arg2 ... argn

Potrzebujesz jednak:

set --

Aby opróżnić tę listę (lub shift "$#") i

set -- -foo

ustawić $1na coś zaczynającego się od -lub +, więc dobrym nawykiem jest zawsze używać, set --szczególnie gdy używa się dowolnych danych, takich jak set -- "$@" other-argdodawanie argumentów na końcu listy parametrów pozycyjnych.

W powłokach cshrodziny ( csh, tcsh) przypisujesz do argvtablicy:

set argv=(arg1 arg2)

W powłokach z rcrodziny ( rc, es, akanga), do *tablicy:

*=(arg1 arg2)

Możesz jednak przypisywać elementy indywidualnie:

2=arg2

W fishpozycyjne parametry są w argvtablicy wyłącznie (bez $1, $@nie)

set argv arg1 arg2

W zshcelu zapewnienia zgodności z cshmożna również przypisać do argvtablicy:

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

Możesz także:

5=arg5

Oznacza to, że możesz także wykonywać następujące czynności:

argv+=(another-arg)

dodać argument na końcu i:

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

aby usunąć argument z końca lub środka, czego nie można łatwo zrobić z innymi powłokami.

Stéphane Chazelas
źródło
7
set --

jest to czego potrzebujesz:

$ set -- aaa bbb ccc
$ echo "$1"
aaa
$ echo "$2"
bbb
$ echo "$3"
ccc
$ echo "$@"
aaa bbb ccc
dchirikov
źródło