巴什参数报价和eval [英] Bash parameter quotes and eval

查看:158
本文介绍了巴什参数报价和eval的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经写了一个bash日志库与我公司目前正在使用一些复杂的脚本来实现。我一直在压力固定提供脚本文件名($ {} BASH_SOURCE),并作出日志呼叫时调用脚本的行号($ {} LINENO)。但是,我并不希望有依靠用户或执行脚本在这两个变量作为参数传递。如果这是C / C ++,我只想创建prepends__FILE__和__LINE__参数列表的宏。

I've written a bash logging library to be implemented with some complex scripts that my company is currently using. I've been deadset on providing the script filename (${BASH_SOURCE}) and the line number (${LINENO}) of the calling script when making the log calls. However, I didn't want to have to rely on the user or implementing script to pass in these two variables as parameters. If this were C/C++, I would just create a macro that prepends "__FILE__" and "__LINE__" to the parameter list.

我终于能得到这部分工作。这里有一些非常简单的摘要作为概念验证:

I was finally able to get this part working. Here are some much-simplified abstracts as a proof of concept:

这里的日志库:

# 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

这工作pretty好(而且,我很高兴得到它在第一个工作日)。但是,这有一个突出的问题:报价和eval之间的相互作用。如果我拨打电话:

This works pretty well (and, I was thrilled to get it working at first). However, this has one glaring problem: the interaction between quotes and eval. If I make the call:

${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。有了这个实现,上面的调用失败(只有一个引语)的工作就好了。

Now, I believe that I understand why this is happening. The quoted parameters are kept intact as they're passed to eval, but at that point, the content is placed as-is into the resulting command string. I know that I can fix this by doing some escaping; however, I REALLY do not want to force the implementing scripts to have to do this. Before I implemented this "eval macro" capability, I had users make calls directly to "_log" and allowed them to optionally pass in "${LINENO}." With this implementation, The failing call above (with only a quoted sentence) worked just fine.

在最基本的层面上,我真正想要的是一个脚本,能够调用的 [日志功能/宏]字符串登录特殊characers的并具有生成的日志信息包含调用脚本的文件名和行数,随后该日志消息。如果可能的话,我会认为我很接近,但如果有我俯瞰这将需要不同的方法什么的,我接受这一点。我不能强迫用户逃避所有的消息,因为这可能会导致他们不使用这个库。这是这样一个问题,如果我不能找到一个解决方案,这一点,我很可能会恢复到旧的能力(这需要$ {} LINENO作为函数参数传递 - 这是侵入少得多)。

At the most basic level, all I really want is for a script to be able to call [log function/macro] "String to log with special characers" and have the resulting log message contain the filename and line number of the calling script, followed by the log message. If it's possible, I would assume that I'm very close, but if there's something I'm overlooking that would require a different approach, I'm open to that as well. I can't force the users to escape all of their messages, as that will likely cause them to not use this library. This is such a problem that if I can't find a solution to this, I'll likely revert to the old capability (which required ${LINENO} to be passed as a function parameter - this was much less intrusive).

TLDR :有没有什么办法让EVAL一个报价参数中尊重特殊字符,而不必躲避他们。

TLDR: Is there any way to get eval to respect special characters within a quoted parameter, without having to escape them?

推荐答案

我建议避免评估如果可能的话。为了您的日志使用的情况下,你可能需要看一下shell内建主叫。如果您需要了解更多信息,您可以使用变量 BASH_SOURCE BASH_LINENO FUNCNAME 。请注意,所有这些变量是数组,并包含完整的调用堆栈。请看下面的例子:

I recommend avoiding eval if possible. For your logging use case, you might take a look at the shell builtin caller. If you need more information, you can use the variables BASH_SOURCE, BASH_LINENO and FUNCNAME. Note that all of these variables are arrays and contain the full call stack. See the following example:

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

这篇关于巴什参数报价和eval的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆