Можно ли использовать переменные параметров оболочки ($ 1,…, $ @) непосредственно в CLI?

9

Иногда необходимо эмулировать и проверять вышеуказанные переменные в небольших примерах, а затем сразу же скопировать их в какой-либо сценарий и т. Д.

Я попытался решить, используя простой пример, следующими способами:

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

и с другими комбинациями. Также экспериментировал, добавив директиву интерпретатора shebang #!/bin/sh -x, но не получил желаемого результата.

Могу ли я сделать это просто?

апостол
источник
1
(find $1) /tmpэто синтаксическая ошибка На самом деле (any-command) more-argumentsэто синтаксическая ошибка. Можете ли вы объяснить по-другому, что вы пытаетесь сделать?
Селада,
2
@Celada, это не ошибка синтаксиса в оболочках rcсемьи ( rc, es, akanga...), где в этом случае это эквивалентно find $1 /tmp.
Стефан Шазелас

Ответы:

15

Первый аргумент после sh -c inline-scriptидет к $0(который также используется для сообщений об ошибках), а остальные идут $1, $2...

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

Итак, вы хотите:

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

(в прежние времена вы могли найти shреализации, в которые $1вместо этого входил первый аргумент , так что вы бы сделали:

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

Или:

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

чтобы объяснить оба поведения, но эти оболочки исчезли теперь, когда POSIX является распространенным и общедоступным).


Если вы хотите установить $1, $2в локальной области внутри текущей оболочки, вы будете использовать функции. В борновоподобных оболочках:

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

Некоторые оболочки поддерживают анонимные функции. Это случай zsh:

(){find "$1"} /tmp

Или es:

@{find $1} /tmp

Для постоянного изменения текущих позиционных параметров синтаксис зависит от оболочки. dchirikov уже покрыл Bourne-подобных оболочках (Bourne, Korn, bash, zsh, POSIX, ash, yash...).

Синтаксис:

set arg1 arg2 ... argn

Однако вам необходимо:

set --

Чтобы очистить этот список (или shift "$#") и

set -- -foo

установить $1что-то, начинающееся с -или +, так что это хорошая привычка всегда использовать, set --особенно когда используются произвольные данные, такие как set -- "$@" other-argдобавление аргументов в конец списка позиционных параметров.

В оболочках cshсемейства ( csh, tcsh) вы присваиваете argvмассиву:

set argv=(arg1 arg2)

В оболочках rcсемьи ( rc, es, akanga), в *массиве:

*=(arg1 arg2)

Хотя вы также можете назначить элементы индивидуально:

2=arg2

В fishпозиционные параметры в argvмассиве только (нет $1, $@есть):

set argv arg1 arg2

В zshцелях совместимости cshвы также можете присвоить argvмассиву:

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

И вы также можете сделать:

5=arg5

Это означает, что вы также можете делать такие вещи, как:

argv+=(another-arg)

добавить аргумент в конец, и:

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

удалить аргумент с конца или середины, что вы не можете легко сделать с другими оболочками.

Стефан Шазелас
источник
7
set --

это то, что вам нужно:

$ set -- aaa bbb ccc
$ echo "$1"
aaa
$ echo "$2"
bbb
$ echo "$3"
ccc
$ echo "$@"
aaa bbb ccc
dchirikov
источник