当前位置: 首页>>技术教程>>正文


$BASH_COMMAND变量有什么用?

, ,

问题描述

根据Bash manual,环境变量BASH_COMMAND包含

The command currently being executed or about to be executed, unless the shell is executing a command as the result of a trap, in which case it is the command executing at the time of the trap.

撇开陷阱的情况,如果我理解正确,这意味着当我执行命令时,变量BASH_COMMAND包含该命令。尽管可能有人争辩说,因为它是“当前正在执行或将要执行的命令”,但仍不确定是否在执行命令后未设置该变量(即仅在命令运行时可用)。 ,不是刚刚执行的命令。

但是让我们检查一下:

$ set | grep BASH_COMMAND=
$ 

空的我本来希望看到BASH_COMMAND='set | grep BASH_COMMAND='或也许只是BASH_COMMAND='set',但空虚使我感到惊讶。

让我们尝试其他方法:

$ echo $BASH_COMMAND
echo $BASH_COMMAND
$ 

嗯,这很有道理。我执行命令echo $BASH_COMMAND,因此变量BASH_COMMAND包含字符串echo $BASH_COMMAND。为什么这次这次有效,但以前却没有呢?

让我们再次执行set的操作:

$ set | grep BASH_COMMAND=
BASH_COMMAND='echo $BASH_COMMAND'
$

等一下它是在我执行该echo命令时设置的,此后并没有取消设置。但是,当我再次执行set时,未将BASH_COMMAND设置为set命令。无论我在这里执行set命令的频率如何,结果都保持不变。那么,在执行echo时是否设置了变量,而在执行set时没有设置?让我们来看看。

$ echo Hello AskUbuntu
Hello AskUbuntu
$ set | grep BASH_COMMAND=
BASH_COMMAND='echo $BASH_COMMAND'
$

什么?所以变量是在我执行echo $BASH_COMMAND时设置的,而不是在我执行echo Hello AskUbuntu时设置的?现在有什么区别?仅当当前命令本身实际强制 shell 程序评估变量时才设置变量吗?让我们尝试一些不同的东西。也许这次是一些外部命令,而不是内置的bash来进行更改。

$ /bin/echo $BASH_COMMAND
/bin/echo $BASH_COMMAND
$ set | grep BASH_COMMAND=
BASH_COMMAND='/bin/echo $BASH_COMMAND'
$

嗯,好的。。。再次设置变量。那么我目前的猜测正确吗?仅在需要评估变量时设置变量吗?为什么?为什么?出于性能原因?让我们再尝试一次。我们将尝试在文件中grep $BASH_COMMAND,并且由于$BASH_COMMAND随后应包含grep命令,因此grep应该grep该grep命令(即,本身)。因此,让我们制作一个合适的文件:

$ echo -e "1 foo\n2 grep\n3 bar\n4 grep \$BASH_COMMAND tmp" > tmp
$ grep $BASH_COMMAND tmp
grep: $BASH_COMMAND: No such file or directory
tmp:2 grep                                      <-- here, the word "grep" is RED
tmp:4 grep $BASH_COMMAND tmp                    <-- here, the word "grep" is RED
tmp:2 grep                                      <-- here, the word "grep" is RED
tmp:4 grep $BASH_COMMAND tmp                    <-- here, the word "grep" is RED
$ set | grep BASH_COMMAND=
BASH_COMMAND='grep --color=auto $BASH_COMMAND tmp'
$

好吧,有趣。命令grep $BASH_COMMAND tmp扩展为grep grep $BASH_COMMAND tmp tmp(当然,变量仅扩展了一次),因此我为grep进行了grep操作,一次是在不存在的文件$BASH_COMMAND中,一次是在文件tmp中。

问题1:我目前的假设是否正确:

  • BASH_COMMAND仅在命令尝试对其求值时才置位。和

  • 即使描述可能使我们相信,在执行命令后仍未设置它?

问题2:如果可以,为什么?性能?如果否,那么如何解释以上命令序列中的行为?

问题3:最后,在任何情况下都可以实际使用此变量吗?我实际上是试图在$PROMPT_COMMAND中使用它来分析正在执行的命令(并根据它做一些事情),但是我不能,因为在$PROMPT_COMMAND中,我立即执行了一个命令来查看变量$BASH_COMMAND ,该变量将获得该命令的设置。即使当我在$PROMPT_COMMAND的开头直接执行MYVARIABLE=$BASH_COMMAND时,MYVARIABLE也包含字符串MYVARIABLE=$BASH_COMMAND,因为赋值也是命令。 (此问题与我如何在$PROMPT_COMMAND执行中如何获取当前命令无关。我知道还有其他方法。)

这有点像海森堡的不确定性原理。只需观察变量,即可对其进行更改。

最佳办法

回答第三个问题:当然,它可以按照Bash手册明确提示的方式进行有意义的使用-陷阱,例如。 G。:

$ trap 'echo ‘$BASH_COMMAND’ failed with error code $?' ERR
$ fgfdjsa
fgfdjsa: command not found
‘fgfdjsa’ failed with error code 127
$ cat /etc/fgfdjsa
cat: /etc/fgfdjsa: No such file or directory
‘cat /etc/fgfdjsa’ failed with error code 1

次佳办法

现在已经回答了Q3(我认为正确的是:BASH_COMMAND在陷阱中有用,几乎在其他任何地方都没有用),现在让我们来看看Q1和Q2。

Q1的答案是:您的假设的正确性尚不确定。当他们要问未指明的行为时,这两个要点都不成立。根据其指定,在该命令的执行期间,将BASH_COMMAND的值设置为该命令的文本。规范没有说明在任何其他情况下(即没有命令执行时)其值必须是什么。它可以具有任何值或根本没有任何值。

问题2的答案:“否,那么如何解释以上命令序列中的行为?”然后从逻辑上讲(如果有些书呆子):由以下事实解释:BASH_COMMAND的值未定义。由于其值是不确定的,因此它可以具有任何值,这正是序列显示的值。

后记

我认为您确实在规范中遇到了一个弱点。在这里你说:

Even when I do MYVARIABLE=$BASH_COMMAND right at the beginning of my $PROMPT_COMMAND, then MYVARIABLE contains the string MYVARIABLE=$BASH_COMMAND, because an assignment is a command too.

我阅读bash手册页的方式不是斜体。 SIMPLE COMMAND EXPANSION部分说明了如何首先在命令行中保留变量分配,然后再保留

If no command name results [in other words, there were only variable assignments], the variable assignments affect the current shell environment.

这向我表明,变量赋值不是命令(因此免于出现在BASH_COMMAND中),就像其他编程语言一样。然后,这也可以解释为什么set的输出中没有行BASH_COMMAND=set,而set本质上是用于变量分配的语法’marker’。

OTOH,在该部分的最后一段中说

If there is a command name left after expansion, execution proceeds as described below. Otherwise, the command exits.

…表示不正确,变量分配也是命令。

参考资料

本文由Ubuntu问答整理, 博文地址: https://ubuntuqa.com/article/11402.html,未经允许,请勿转载。