Я написал библиотеку регистрации bash, которая будет реализована с помощью некоторых сложных сценариев, которые моя компания использует в настоящее время. Я делал ошибку при предоставлении имени файла сценария ($ {BASH_SOURCE}) и номера строки ($ {LINENO}) вызывающего скрипта при выполнении вызовов журнала. Однако я не хотел полагаться на пользователя или реализацию скрипта для передачи этих двух переменных в качестве параметров. Если бы это был C/C++, я бы просто создал макрос, который добавляет «__FILE__» и «__LINE__» в список параметров.Котировки параметра Bash и eval
Я, наконец, смог получить эту часть работы. Вот некоторые столь упрощенные тезисы как доказательство концепции:
Вот библиотека протоколирования:
# log.sh
LOG="eval _log \${BASH_SOURCE} \${LINENO}"
_log() {
_BASH_SOURCE=`basename "${1}"` && shift
_LINENO=${1} && shift
echo "(${_BASH_SOURCE}:${_LINENO}) [email protected]"
}
и исполнитель сценарий тестирования:
# MyTest.sh
. ./log.sh
${LOG} "This is a log message"
# (test.sh:5) This is a log message
Это работает очень хорошо (и я был взволнован, чтобы заставить его работать сначала). Однако у этого есть одна вопиющая проблема: взаимодействие между кавычками и eval. Если я позвоню:
${LOG} "I'm thrilled that I got this working"
# ./test.sh: eval: line 5: unexected EOF while looking for matching `''
# ./test.sh: eval: line 6: syntax error: unexpected end of file
Теперь я считаю, что понимаю, почему это происходит. Приведенные параметры сохраняются неизменными, поскольку они передаются в eval, но в этот момент содержимое помещается как есть в итоговую командную строку. Я знаю, что могу исправить это, сделав некоторое ускользание; однако, я не хочу, чтобы сценарии реализации должны были это делать. Прежде чем я реализовал эту способность «eval macro», у меня были пользователи, вызывающие вызовы непосредственно на «_log» и разрешившие им опционально передать «$ {LINENO}». С этой реализацией неудачный вызов выше (только с цитируемым предложением) работал нормально.
На самом базовом уровне, все, что я действительно хочу, чтобы сценарий, чтобы иметь возможность вызвать [войти функции/макрос] «Строка для входа со специальной characers» и имеет результирующее сообщение журнала содержит имя файла и строку номер вызывающего скрипта, за которым следует сообщение журнала. Если это возможно, я бы предположил, что я очень близко, но если есть что-то, что я упускаю из виду, это потребует другого подхода, я тоже к этому открыт. Я не могу заставить пользователей избегать всех своих сообщений, поскольку это, вероятно, заставит их не использовать эту библиотеку. Это такая проблема, что, если я не могу найти решение этого, я, скорее всего, вернусь к старой возможности (которая требует, чтобы $ {LINENO} передавался как параметр функции - это было гораздо менее навязчивым).
TLDR: Есть ли способ получить знак eval для соблюдения специальных символов в указанном параметре, без необходимости их избегать?
Если вы используете конкретные конструкции bash, ваш сценарий ведения журнала не должен называться «log.sh». Это должно быть «log.bash». –
@WilliamPursell - Я сделал некоторые поиски и не смог найти какой-либо стандарт в отношении соглашений об именах сценариев оболочки. Фактически, большинство людей, похоже, вообще не имеют суффикса. Честно говоря, я никогда не видел ничего, кроме «\ *. Sh» (или скрипта без расширения/суффикса). И во всей практичности это не должно иметь никакого влияния, верно? Интерпретатор либо извлекается из первой строки скрипта, либо используется ваша текущая оболочка. Похоже, это по сути сводится к личным предпочтениям. Но, возможно, «\ *. Sh» может означать пользователя, что сценарий использует «sh». – LousyG
Единственное практическое воздействие было бы, если разработчик использует ваши функции с другой оболочкой. С именем '* .sh' разработчик разумно предположил бы, что ваша библиотека может быть получена в zsh-скрипте. –