![Bash распознает аргумент функции как программу](https://rvso.com/image/1665759/Bash%20%D1%80%D0%B0%D1%81%D0%BF%D0%BE%D0%B7%D0%BD%D0%B0%D0%B5%D1%82%20%D0%B0%D1%80%D0%B3%D1%83%D0%BC%D0%B5%D0%BD%D1%82%20%D1%84%D1%83%D0%BD%D0%BA%D1%86%D0%B8%D0%B8%20%D0%BA%D0%B0%D0%BA%20%D0%BF%D1%80%D0%BE%D0%B3%D1%80%D0%B0%D0%BC%D0%BC%D1%83.png)
Я новичок в синтаксисе bash, и у меня есть фрагмент кода в файле '.bash_aliases'. Он получает либо целое число в качестве аргумента, либо букву 'c', когда он получает целое число, он помещает это целое число в переменную окружения, которая может использоваться веб-серверами в качестве порта. Когда он получает букву 'c' в качестве входных данных, он очищает переменную.
Когда я пытаюсь выполнить команду с целым числом, я получаю ошибку
main@linuxWSL:~$ serverp 2000
-bash: [: missing `]'
2000: command not found
и когда я пробую это с буквой «с», я получаю
main@linuxWSL:~$ serverp c
-bash: [: missing `]'
c: command not found
Вот мой bash-код:
serverp () {
if [ "$1" = "clear" || "$1" = "c" ]
then
unset PORT
echo -e "\e$CLEAR$GREEN""mWebServer port has been reset!""$CLEAN"
return 0
fi
export PORT="$1"
}
Кто-нибудь может мне помочь? Спасибо!
решение1
[
не является ключевым словом в Bash, которое заставило бы анализатор оболочки интерпретировать остальную часть командной строки по-другому. [
является командой, подобной cat
или echo
. [
(подобно echo
) является встроенной функцией в Bash, но это означает только то, что ее можно запустить, не порождая дополнительный процесс; она все равно ведет себя как команда.
И для ясности: [ … ]
это не часть if … then …
синтаксиса. if
Просто проверяет статус завершения некоторого кода: if true; then …
допустим, if sleep 5; then …
допустим, аналогично if [ … ]; then …
допустим (если [ … ]
часть сама по себе является допустимой командой).
[
Вероятно, в вашей системе есть исполняемый файл. Попробуйте type -a [
. Сравните с type -a [[
. В отличие от [
, [[
является ключевым словом в Bash, и оно заставляет синтаксический анализатор обрабатывать вещи между [[
и ]]
особым образом.
[
не является ключевым словом. Правильно написанная [ … ]
команда, где ]
— это просто последний аргумент. [
требует ]
в качестве последнего аргумента, иначе она отказывается работать. Это сделано только для того, чтобы [ … ]
выделиться в блок, как будто это какой-то особый синтаксис; но это не особый синтаксис.
Ваш [ "$1" = "clear" || "$1" = "c" ]
интерпретируется оболочкой как [ "$1" = "clear"
и "$1" = "c" ]
связан с ||
. Таким образом, есть две команды. Первая команда — [ "$1" = "clear"
, [
выполняется, она не получает ]
в качестве последнего аргумента, жалуется и завершается с ненулевым статусом выхода. Из-за ненулевого статуса и из-за ||
, оболочка пытается выполнить вторую команду, которая начинается с того, что "$1"
расширяется до. Таким образом, первый аргумент вашего скрипта интерпретируется как исполняемый файл для запуска.
Исправьте это [ … || … ]
так:
[ "$1" = "clear" ] || [ "$1" = "c" ]
Этот фрагмент состоит из двухдействительный [
команды. Он должен делать то, что вы хотите.
Примечание [[ "$1" = "clear" || "$1" = "c" ]]
— это рабочий фрагмент кода, а [ "$1" = "clear" || "$1" = "c" ]
не . Это потому, что , [[
это не команда. Это ключевое слово, и оно заставляет парсер оболочки обрабатывать все до ]]
по-особенному; это включает ||
. Есть и другиеразличия между [[
и[
, не меняйте их местами вслепую.
Встроенная поддержка [
Bash-o
или(и -a
дляи), так что это тоже сработает:
[ "$1" = "clear" -o "$1" = "c" ]
Это ваш код, где ||
(специальный для оболочки) был заменен на -o
(неспециальный для оболочки). -o
Однако вам следует избегать. ИзЭта статья:
Двоичные
-a
и-o
[…] являются расширениями XSI стандарта POSIX. Все они помечены как устаревшие в POSIX-2008. Их не следует использовать в новом коде. Одна из практических проблем с[ A = B -a C = D ]
(or-o
) заключается в том, что POSIX не определяет результаты командыtest
or[
с более чем 4 аргументами. Вероятно, это работает в большинстве оболочек, но вы не можете на это рассчитывать. Если вам нужно писать для оболочек POSIX, то вместо этого вам следует использовать две командыtest
or[
, разделенные оператором&&
.
Обратите внимание, что статья подробно описывает -a
, поэтому " &&
оператор вместо". В вашем случае это -o
и ||
соответственно. Два теста, разделенные оператором, ||
— это как раз наше решение.
решение2
Его if [ "$1" = "clear" ] || [ "$1" = "c" ]
.