Lou*_*syG 8 variables bash shell eval
我编写了一个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}) $@"
}
Run Code Online (Sandbox Code Playgroud)
并实施测试脚本:
# MyTest.sh
. ./log.sh
${LOG} "This is a log message"
# (test.sh:5) This is a log message
Run Code Online (Sandbox Code Playgroud)
这非常有效(而且,我很高兴让它首先工作).然而,这有一个明显的问题:引号和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
Run Code Online (Sandbox Code Playgroud)
现在,我相信我理解为什么会这样.引用的参数在传递给eval时保持不变,但此时,内容按原样放入生成的命令字符串中.我知道我可以通过做一些逃避来解决这个问题.但是,我真的不想强制执行脚本必须这样做.在我实现这个"eval宏"功能之前,我让用户直接调用"_log"并允许他们选择传入"$ {LINENO}".通过这个实现,上面的失败调用(只有引用的句子)工作得很好.
在最基本的层面上,我真正想要的是一个脚本能够调用[log function/macro]"String to special with characers"并且生成的日志消息包含调用脚本的文件名和行号,然后是日志消息.如果可能的话,我会认为我非常接近,但是如果有一些我忽略的东西需要采用不同的方法,我也会对此持开放态度.我无法强制用户转义所有邮件,因为这可能会导致他们不使用此库.这是一个问题,如果我找不到解决方案,我可能会恢复旧的功能(需要$ {LINENO}作为函数参数传递 - 这是更少侵入性).
TLDR:有没有办法让eval尊重引用参数中的特殊字符,而不必转义它们?
nos*_*sid 14
我建议eval尽可能避免.对于您的日志记录用例,您可以查看内置的shell caller.如果您需要了解更多信息,您可以使用变量BASH_SOURCE,BASH_LINENO和FUNCNAME.请注意,所有这些变量都是数组并包含完整的调用堆栈.请参阅以下示例:
#! /bin/bash
function log() {
echo "[$( caller )] $*" >&2
echo "BASH_SOURCE: ${BASH_SOURCE[*]}"
echo "BASH_LINENO: ${BASH_LINENO[*]}"
echo "FUNCNAME: ${FUNCNAME[*]}"
}
function foobar() {
log "failed:" "$@"
}
foobar "$@"
Run Code Online (Sandbox Code Playgroud)