在 zsh fc 命令中使用通配符

在 zsh fc 命令中使用通配符

我在 zshrc 中有一个别名设置,可以使用 sudo 重新运行命令:

alias please='sudo $(fc -nl -1)'

除了我在上一个命令中使用通配符的情况之外,它的工作效果令人钦佩,例如“rm *.o”,该命令将返回类似“rm:无法删除“*.o”:没有这样的文件或目录”。

有没有好的方法让这个别名正确使用通配符?

答案1

不,没有什么好方法可以“让这个别名正确使用通配符”,因为“正确”在不同情况下意味着不同的事情。例如,如果命令行包含命令替换,您是否打算以 root 身份运行其他命令?您所追求的自动化非常方便快速地做错误的事情。这就像过马路时闭上眼睛,因为看车太烦人了。

我的建议是输入命令Up Home s u d o Space并花点时间重新阅读以确保你正在做的是你想要做的。

话虽这么说,如果你喜欢冒险,当然,你可以让你的计算机做某物。这是两个执行不同操作的解决方案。

以下函数假定前一个命令是对外部命令的调用。它使用相同的参数调用外部命令,但带有sudo前缀。这意味着诸如通配符扩展、变量替换和命令替换之类的事情都是在 shell 的上下文中调用的。

please () {
  setopt local_options err_exit
  local args
  eval "args=($history[$((HISTCMD-1))])"
  print -lr Running sudo "$args[@]"
  sleep 2
  sudo "$args[@]"
}

以下命令假设前面的命令没有修改 shell 环境并且不依赖任何环境变量。它以 root 身份运行整个命令行,包括通配符扩展、命令替换等。

please () {
  sudo zsh -c "$history[$HISTCMD]"
}

答案2

唯一的解决方案似乎是:

alias please='eval sudo $(fc -nl -1)'

答案3

Zsh 禁用输出的通配符命令替换除非GLOB_SUBST设置:

如果设置了该选项GLOB_SUBST,则任何不带引号的命令替换的结果(包括刚才提到的特殊形式)都可以生成文件名。

您可以启用它,然后您的别名应该可以使用。您还可以使用数组history:

history
该关联数组将历史事件编号映射到完整的历史记录行。尽管它呈现为关联数组,但${history[@]}保证按从最近到最旧的历史事件的顺序(即按历史事件编号递减)的顺序返回所有值 ( ) 的数组。

然后使用模式替换标志有选择地启用GLOB_SUBST

${=spec}
在spec评估过程中使用for的规则进行分词SH_WORD_SPLIT,但无论参数是否出现在双引号中;如果=加倍,请将其关闭。这会强制参数扩展在替换之前被分割成单独的单词,并使用 IFS 作为分隔符。 [...]

${~spec}
打开GLOB_SUBSTspec评估选项;如果~ 加倍,请将其关闭。

例子:

% alias s='sudo ${~=${history[@]}[1]}'
% echo *                                   
a b c
% s
[sudo] password for muru: 
a b c
% echo [a]
a
% s       
a

相关内容