与我了解到的现有$_
代表类似!-1:$
,我想为 等创建别名$__
,$___
以此类推,引用第二个或第三个 -last 命令。我尝试过添加
alias "$__"='!-2:$'
在我的.zshrc.local
。如果可能的话,我想编写一个 zsh 函数,它根据下划线的数量返回第 n 个最后命令的第一个参数。
arch linux kernel 5.1.4-arch
zsh 5.7.1 (x86_64-pc-linux-gnu)
答案1
该功能已经存在
您不需要任何复杂的操作即可访问先前命令的最后一个单词。只需按ESC-.
(即Alt+ .)或ESC-_
(即Alt+ _)。这将调用编辑器命令insert-last-word
,它插入上一个命令行中的最后一个单词。再次按该键可从命令行获取之前的最后一个单词,依此类推。如果您按了ESC-.
太多次,请使用C-_
(撤消)返回到之前的单词。
在 vi 模式下,该命令默认不绑定到按键,但您可以使用bindkey
.
您可以传递一个数字参数来获取不同的单词:正数从右侧开始(1 是最后一个单词),零或负数从左侧开始(0 是第一个单词,通常是命令名称,1 是命令名称)第一个参数之后的单词,等等)。例如,ESC . ESC - ESC 1 ESC .
插入倒数第二个命令的第一个参数。
通过在 周围定义您自己的小部件,可以对此命令进行许多变体zle insert-last-word
。 Zsh 附带copy-earlier-word
和smart-insert-last-word
您可能会发现它对于按原样使用或作为代码示例很有用。
如果您确实想$__
扩展到前一个命令的最后一个单词,我将在下面给出一些解决方案,但首先我需要解释一下发生了什么。
为什么你的尝试不起作用
首先,你并没有定义你认为你正在定义的东西。定义一个别名,其名称是执行别名定义时alias "$__"=…
变量的当前值。__
这可能是空的,因此您正在执行alias ='!-2:$'
查找'!-2:$'
在搜索路径上调用的命令(=
扩张文件名扩展的一部分)。要定义名为 的别名$__
,您需要传递$__
给别名命令,例如 withalias '$__'=…
或alias \$__=…
。
其次,别名仅在命令位置扩展,即作为命令的第一个单词(在任何前导变量赋值和重定向之后)。为了使这个别名有用,它需要是一个全局别名:alias -g '$__'=…
第三,这个别名不会做任何有用的事情,因为别名扩展发生在历史扩展之后。
darkstar
darkstar% alias -g '$__'='!-2:$'
darkstar% echo $__
!-2:$
$_
不“代表” !-1:$
。$_
和!-1:$
是在常见情况下访问相同信息的两种方法。你可以说$_
“是一个别名” !-1:$
,或者相反,!-1:$
“是一个别名” $_
,但这是在一般英语意义上使用“别名”,而不是shell别名的技术意义上,而且它是不精确的,因为两者不' t 总是具有相同的值。!-1:$
是一个历史扩展( !
) 构造扩展到遗言(:$
) 的上一个命令行( -1
)。$_
是一个parameter expansion
使用参数_
shell 将其设置为上一个命令的最后一个参数。如果您运行的命令行不完全是一个简单的命令,则会产生影响,例如:
darkstar% for x in 1 2 3; do echo $x; done
1
2
3
darkstar% echo $_ is not !-1:$
echo $_ is not done
3 is not done
darkstar% echo $_ and !-1:$ are different; echo $_ and !-1:$ are different
echo $_ and done are different; echo $_ and done are different
done and done are different
different and done are different
$__
每个命令定义
您可以定义一个陷阱功能被称为TRAPDEBUG
它在执行每个命令之前运行。记住 的当前值$_
(请注意,您必须首先执行此操作,因为陷阱内的第一个命令将覆盖_
),然后“移动”多下划线变量。
darkstar% TRAPDEBUG () { _0=$_; ___=$__; __=$_1; _1=$_0; }
darkstar% echo one
one
darkstar% echo two
two
darkstar% echo three
three
darkstar% echo $_,$__,$___
three,two,one
$_1
并不总是与 相同$_
,因为调试陷阱不会在导致_
设置的完全相同的情况下运行,但它非常接近。
$__
每个命令行定义
您可以注册一个钩子函数在输入命令行之前或之后运行。在这种情况下,要么precmd
或者preexec
。它们分别在执行命令之前和之后运行。
preexec_set_underscore_variables () {
___=$__
__=$_1
_1=$historywords[1]
}
preexec_functions+=(preexec_set_underscore_variables)
我用historywords
从命令行获取最后一个单词。我把它存储起来,_1
因为_
已经被占用了。该函数将最后一个单词历史变量“移动”1。
darkstar% echo one
one
darkstar% echo two
two
darkstar% echo three
three
darkstar% echo $_ $__ $___
three two one