在DEBUG陷阱中保留$_的Bash命令

4
在中,手册$_应该是“上一个执行的命令的最后一个参数”。
以下是期望的行为:
$ echo 1 2 3
1 2 3
$ echo $_
3
$ 

使用DEBUG陷阱时,$_基于陷阱运行的最后一条命令(以下示例中为date),而不是用户输入的最后一条命令:
$ exec bash
$ unset PROMPT_COMMAND
$ trap date DEBUG
$ echo 1 2 3
Sat Dec  3 11:54:33 ICT 2016
1 2 3
$ echo $_
Sat Dec  3 11:54:37 ICT 2016
date
$ # User blinks in confusion and says "but I didn't just type date!"

默认情况下,设置DEBUG陷阱会更改$_的默认行为。

无论是chruby还是bash-preexec都受此影响。

有趣的是,在zsh中,这一点可以正常工作:

$ zsh
genesis% trap date DEBUG
genesis% echo 1 2 3
Sat Dec  3 12:18:01 ICT 2016
1 2 3
genesis% echo $_
Sat Dec  3 12:18:04 ICT 2016
3
genesis%

如何在使用DEBUG陷阱时保留$_的值?
1个回答

5
值得注意的是,“上一个执行的命令的最后一个参数”包括文字“上一个执行的命令”,而不是“用户输入的最后一个命令”;在这方面,bash 的行为与其文档承诺的一样。
但是不用担心:除非您的陷阱返回非零值(因此在运行它们之前中止运行的命令),否则很容易解决这个问题。
trapfunc() { local old_=$1; date; : "$old_"; }
trap 'trapfunc "$_"' DEBUG

你为什么不引用 $1 - Tom Hale
4
变量展开和单词拆分在赋值语句中不会发生:a='hello world *.txt'; b=$a,此时 b 的值就是 a 的值,没有任何问题。 - Andreas Louv
虽然我通常支持不过度引用,并且通常不在作业的右手边使用双引号,但我认为最佳实践确实要求在右手边使用双引号。可能应该是local old_="$1";(明确一点,这完全是一个风格上的问题,没有实际影响)。 - undefined
@WilliamPursell,我将任务从local声明中分离出来,现在更少了歧义。 - undefined

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接