Eval и exec с подстановкой переменных

Я предполагаю, что у вас уже есть способ получить переменные из ввода , поскольку вы упомянули параметр --platforms. Вы можете использовать регулярные выражения для соответствия допустимым условиям.

regex='^(mac|win|linux(32|64)|all)(,(mac|win|linux(32|64)|all))*$'
if [[ $1 =~ $regex ]]; then 
  echo "ok"
else 
  echo "not ok"
fi

Это должно удовлетворять всем требованиям:

$ ./stack.sh linux32
ok
$ ./stack.sh linux32,mac
ok
$ ./stack.sh lulz
not ok
$ ./stack.sh linux32,lulz
not ok

Конечно, это не мешает людям использовать «все, все, все, все», но, по крайней мере, это можно уменьшить, когда на самом деле запустят материал позже.

Преимущества этого метода включают в себя возможность зацикливаться, пока пользователь не поймет это правильно, если вы используете команду чтения, указанную в первом сообщении. К недостаткам можно отнести то, что просто взглянуть на него немного запутанно.

regex='^(mac|win|linux(32|64)|all)(,(mac|win|linux(32|64)|all))*$'
while ! [[ $REPLY =~ $regex ]]; do
  read -p "For what platforms do you wish to build [mac/win/linux32/linux64/all] ? "
done
0
05.02.2019, 09:49
2 ответа

Во втором фрагменте кода вы удалили двойные кавычки вокруг аргумента eval. Не делай этого. Их удаление сделало бы ()специальным для оболочки (, она запускает вспомогательную -оболочку ).

Вместо:

app=main
eval "exec gunicorn --chdir /this/dir package.sub:call_$app'()' -b 0.0.0.0:80"

Круглые скобки по-прежнему должны быть заключены в кавычки, так как evalre -оценивает строку. Расширение переменной $appбудет выполнено до вызова eval.

или,

app=main
eval "exec gunicorn --chdir /this/dir 'package.sub:call_$app()' -b 0.0.0.0:80"

что может выглядеть лучше.

Обратите внимание, что ${APP}и $APPидентичны во всех отношениях, за исключением случаев, когда сразу за ними следует символ, допустимый в имени переменной (, как в"${APP}x"). Здесь {...}не нужен. Кроме того, используйте имена переменных нижнего регистра -, чтобы избежать случайных конфликтов с существующей переменной среды.

Я не думаю, что здесь нужны ни eval, ни exec. Строка, похоже, не нуждается в оценке -с eval, а execзаменит текущий процесс оболочки на gunicorn(. Я не знаю, хотите ли вы этого или нет. ).

Может хватит

app=main
gunicorn --chdir /this/dir "package.sub:call_$app()" -b 0.0.0.0:80

Обратите внимание на двойные -кавычки.

Связанные:

1
28.01.2020, 02:41

Вы выполняете сложную задачу :Оболочка должна выполнить 11 проходов (и каждый проход искажает ввод для следующего шага ).

Ваш код

APP=main
eval exec gunicorn --chdir /this/dir package.sub:call_${APP}() -b 0.0.0.0:80

Чтобы понять, уберите eval:

exec gunicorn --chdir /this/dir package.sub:call_${APP}() -b 0.0.0.0:80

Обратите внимание, что :первый пример аналогичен, вы удаляете evalи двойные кавычки, поэтому вы по-прежнему получаете тот же результат.

Теперь у вас есть (), которые зарезервированы (, что является чем-то особенным, потому что токен не может быть неправильно истолкован другими способами в таком случае :нет префикса, мы не в контексте команды (, поэтому для вызова подоболочки, используя круглые скобки ). Обратите внимание :, это связано с 11 шагами и порядком токенизации. Вероятно, читая правила, мы понимаем, почему это так. (а синтаксический анализатор оболочки разработан очень давно, поэтому он прост)

Таким образом, вы должны указать оболочке перейти ()к следующему шагу парсера.

Вы можете использовать побег(\):

exec gunicorn --chdir /this/dir package.sub:call_${APP}\(\) -b 0.0.0.0:80

или кавычки:

exec gunicorn --chdir /this/dir package.sub:call_${APP}'()' -b 0.0.0.0:80

Обратите внимание, :вам не нужно заключать в кавычки все "слово" (параметр ), вы можете заключать в кавычки только часть, чтобы не заключать в одиночные кавычки ${APP}(, которые необходимо расширить ).

Для первого примера можно использовать двойные кавычки:

eval "exec gunicorn --chdir /this/dir \"package.sub:call_main()\" -b 0.0.0.0:80"

Таким образом, eval удалит внешние кавычки, а exec увидит внутренние кавычки (без экранирования)

0
28.01.2020, 02:41

Теги

Похожие вопросы