gpt4 book ai didi

Bash 参数引号和 eval

转载 作者:行者123 更新时间:2023-11-29 08:54:14 30 4
gpt4 key购买 nike

我已经编写了一个 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

这工作得很好(而且,一开始我很高兴让它工作)。然而,这有一个明显的问题:引号和 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}”。有了这个实现,上面的失败调用(只有一个引用的句子)工作得很好。

在最基本的层面上,我真正想要的是一个脚本能够调用[日志函数/宏]“使用特殊字符记录的字符串”,并让生成的日志消息包含调用脚本的文件名和行号,后跟日志消息。如果可能的话,我会假设我已经非常接近了,但如果有什么我忽略了需要不同的方法,我也愿意接受。我不能强制用户转义他们所有的消息,因为这可能会导致他们不使用这个库。这是一个如此大的问题,如果我找不到解决方案,我可能会恢复到旧功能(这需要将 ${LINENO} 作为函数参数传递 - 这要少得多)。

TLDR:有什么方法可以让 eval 尊重带引号的参数中的特殊字符,而不必转义它们?

最佳答案

我建议尽可能避免使用 eval。对于您的日志记录用例,您可以查看 shell 内置 caller。如果需要更多信息,可以使用变量 BASH_SOURCEBASH_LINENOFUNCNAME。请注意,所有这些变量都是数组并包含完整的调用堆栈。请参阅以下示例:

#! /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 "$@"

关于Bash 参数引号和 eval,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10707173/

30 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com