Как использовать позиционные параметры с помощью команды "bash -c"?

Я хотел бы узнать лучший способ использования позиционных параметров при использовании команды bash -c.

Страницы руководства указывают для параметра -c, что:

Если после команды command_string есть аргументы, они назначаются параметрам позиционирования, начиная с $0.

Итак, я предполагаю, что следующая форма верна:

$ bash -c 'printf "%s %s %s\n" $0 $1 $2' param1 param2 param3
param1 param2 param3

Однако Я увидел следующую форму, и мне интересно, почему было бы лучше

$ bash -c 'printf "%s %s %s\n" $1 $2' _ param1 param2
param1 param2 

В этом случае символ _ заменяет $0.

Я знаю, что для многих интерпретаторов $0 имеет особое значение (имя команды, все позиционные параметры...), но в этом случае страницы man вполне понятны.

Итак, есть ли что-то неправильное в первом виде и есть ли недостаток использования $0 в качестве первого позиционного параметра для команды bash -c?

Ответы

Ответ 1

bash -c 'printf "%s %s %s\n" $0 $1 $2' param1 param2 param3

Вышеприведенные работы, но многие считают это плохой привычкой. Если вы скопировали код из строки -c в script, это не сработает. Аналогичным образом, если вы хотите скопировать код из строки script в строку -c, это не сработает.

В отличие от следующего вида $1 означает то же самое в строке -c, что это означало бы в функции script или shell:

bash -c 'printf "%s %s %s\n" $1 $2 $3' _ param1 param2 param3

Консистенция стиля программирования уменьшает количество ошибок.

Оболочка рассматривает $0 иначе

Обычно для всех аргументов script используется [email protected] или $*. Обратите внимание, что эти переменные имеют не include $0:

$ bash -c 'echo "$*"' param1 param2 param3
param2 param3
$ bash -c 'echo "[email protected]"' param1 param2 param3
param2 param3

$0 - это имя программы

В обычных скриптах $0 - это имя script. Следовательно, при использовании bash -c некоторые люди предпочитают использовать какое-то значащее имя для параметра $0, например:

bash -c 'printf "%s %s %s\n" $1 $2 $3' bash param1 param2 param3

Или:

bash -c 'printf "%s %s %s\n" $1 $2 $3' printer param1 param2 param3

Этот подход имеет явное преимущество, если строка -c генерирует ошибку. Например, рассмотрим этот script:

$ cat script.sh
#!/bin/bash
bash -c 'grepp misspelling "$1"' BadPgm file.txt

Если мы запустим script, будет создан следующий вывод:

$ ./script.sh 
BadPgm: grepp: command not found

Это идентифицирует источник ошибки как команду в строке bash -c.

Ответ 2

Параметр $0 отличается тем, что он не участвует в shift (например).

Это работает как ожидалось:

$ bash -c 'shift; printf "%s %s %s\n" $1 $2 $3' _ par1 par2 par3 par4
par2 par3 par4

Это не означает:

$ bash -c 'shift; printf "%s %s %s\n" $0 $1 $2' par1 par2 par3 par4
par1 par3 par4

Это определенное в POSIX (упрощенное):

sh -c command_string [имя_команды [аргумент...]]

Поддерживаются следующие дополнительные опции:

-c

Прочитайте команды из операнда command_string. Задайте значение специального параметра 0 (см. Специальные параметры) из значения операнда command_name и позиционных параметров ($ 1, $2 и т.д.) В последовательности из оставшихся операндов аргументов.

Итак, используйте это:

sh -c 'commands' command_name arg1 arg2 arg3 ....