我在 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_SUBST
spec评估选项;如果~
加倍,请将其关闭。
例子:
% alias s='sudo ${~=${history[@]}[1]}'
% echo *
a b c
% s
[sudo] password for muru:
a b c
% echo [a]
a
% s
a