如何从 zsh 函数访问最后一个命令?

How do I access the last command from a zsh function?

我想做这样的事情:

function invim () {
  vim $(!!)
}

但是当我 运行 它时,它说: invim:1: command not found: !!

我认为这是因为 !! 是一个交互式 shell 扩展,在非交互式 scripts/functions 中不可用。在 bash 中,我可以使用 history 命令来完成此操作,但是当我尝试使用它时,它似乎劫持了我的 readline 并且不再允许向上箭头完成工作。

感谢任何帮助!

(注意:这不是一个完整的答案;请参阅评论和


最近的命令在history关联数组中可用,因此这应该类似于您问题中的函数:

function invim {
    vim ${history[@][1]}
}

history[@] 扩展从关联数组获取命令,而 [1] 引用第一项,保证是最新的。

但这可能无法完全满足您的需求。与 bash 不同,zsh 不会将变量扩展重新解析为单词,因此在调用 foo --opt 后立即执行该函数将导致尝试编辑名为 foo --opt 的文件,这可能不存在。我们可以通过使用 ${=...} 的单词扩展来获取第一个单词,将其转换为带有 (A) 参数扩展标志的数组,并添加另一个 [1] 索引运算符。

此外,在许多情况下,此函数只能找到当前目录中的文件。使用 :c 修饰符,该函数可以搜索 PATH 并找到源文件。

综合起来:

function invim {
    vim ${${(A)=history[@][1]}[1]:c}
}

将 Gairfowl 的答案与关联数组结合使用,我能够制定出合适的解决方案:

function invim {                                              
    vim $(bash -c ${history[@][1]})            
}

工作原理如下:

  1. ${history[@][1]}是最新命令的文本,例如find . -type f -name "*.txt"
  2. 运行 该命令在 shell 中使用 bash -c
  3. 生成的标准输出由封闭的 $() 捕获,然后作为要编辑的文件名传递给 vim。这里没有包含引号以允许多行输出全部打开。