Как передать '$' => специальный символ в качестве аргумента для make-файла

Я пытался передать пароль для postgres, который используется в сценарии go и передается через make-файл. Мой пароль содержит символ '$' => make-файл не распознает его как символ. Я пробовал использовать escape-символ '$$' => это тоже не работает

pwsd:=$1

run:
    @echo "Password passed: ${pwsd}"
    @go run ./cmd/web ${pwsd}
input:
make run pwsd = "passwd$"
output:
Password passed: passwd

input:
make run pwsd = "passwd$$"
output:
Password passed: passwdpwsd=passwd$
expected:
Password passed: passwd$

🤔 А знаете ли вы, что...
Shell обеспечивает множество опций и флагов для настройки поведения команд.


1
69
1

Ответ:

Решено

Во-первых, при отладке make-файлов никогда не следует добавлять к рецепту префикс @. Это похоже на запуск вашего компилятора с отправкой вывода в /dev/null.

Сначала вы должны понять, что $ является особенным для оболочки: он вводит переменную оболочки. Таким образом, вам нужно в первую очередь избежать $ из оболочки. Использование двойных кавычек этого не дает: переменные оболочки заключаются в двойные кавычки:

foo=bar
echo "$foo"

показывает bar, а не $foo. Если вы хотите гарантировать, что строка, содержащая $, не будет расширена оболочкой, вам следует использовать одинарные кавычки:

foo=bar
echo '$foo'

Это покажет $foo. Поэтому, если вы хотите, чтобы оболочка видела строку, содержащую знак доллара, вам необходимо (а) вызвать make с правильно заключенным значением и (б) использовать в своем рецепте правильные экранирующие кавычки. Например:

run:
        @echo 'Password passed: ${pwsd}'
        go run ./cmd/web '${pwsd}'

Затем, если вы запустите make pwsd='foo$bar', результат будет:

Password passed: foo$bar
go run ./cmd/web 'foo$bar'

Я должен отметить, что это не удастся, если ваш пароль может содержать одинарные кавычки. Если вы хотите поддержать это, вам придется быть очень изобретательным; что-то вроде этого:

quoted_pwsd = '$(subst ','"'"',$(pwsd))'
run:
        @echo Password passed: ${quoted_pwsd}
        go run ./cmd/web ${quoted_pwsd}

но вы должны быть осторожны, когда используете это.