为历史扩展模式设置别名

为历史扩展模式设置别名

与我了解到的现有$_代表类似!-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-wordsmart-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

相关内容