我编写了一个 bash 日志库,用我公司目前正在使用的一些复杂脚本来实现。在进行日志调用时,我一直在提供脚本文件名 (${BASH_SOURCE}) 和调用脚本的行号 (${LINENO})。但是,我不想依赖用户或实现脚本来将这两个变量作为参数传递。如果这是 C/C++,我只需创建一个宏,将“__FILE__”和“__LINE__”添加到参数列表中。
我终于能够让这部分工作。以下是一些非常简化的摘要作为概念证明:
这是日志库:
# log.sh
LOG="eval _log \${BASH_SOURCE} \${LINENO}"
_log () {
_BASH_SOURCE=`basename "${1}"` && shift
_LINENO=${1} && shift
echo "(${_BASH_SOURCE}:${_LINENO}) $@"
}
和一个实施测试脚本:
# MyTest.sh
. ./log.sh
${LOG} "This is a log message"
# (test.sh:5) This is a log message
这工作得很好(而且,一开始我很高兴能让它工作)。然而,这有一个明显的问题:quotes 和 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 宏”功能之前,我让用户直接调用“_log”并允许他们有选择地传入“${LINENO}”。有了这个实现,上面的失败调用(只有一个引用的句子)工作得很好。
在最基本的层面上,我真正想要的只是让脚本能够调用[log function/macro] "String to log with special characers"并让生成的日志消息包含调用脚本的文件名和行号,随后是日志消息。如果可能的话,我会假设我非常接近,但如果我忽略了某些需要不同方法的东西,我也对此持开放态度。我不能强迫用户转义他们的所有消息,因为这可能会导致他们不使用这个库。这是一个如此大的问题,如果我找不到解决方案,我可能会恢复到旧功能(这需要将 ${LINENO} 作为函数参数传递——这样的侵入性要小得多)。
TLDR:有没有办法让 eval 尊重引用参数中的特殊字符,而不必转义它们?