如何在不使用`!!`的情况下运行最后一个命令?

Bra*_*ldi 4 shell zsh zshrc

我正试图别名_!sudo最后一个命令,但我遇到了障碍.!!似乎没有在我的.zshrc文件中工作,并且sed给了我一再的问题.我尝试使用以下命令,以及它的几个变体,但无济于事.

history | tail -1 | sed -e 's/[^0-9\*\ ]+/\0/g'

但是,这仍然将管道输入解释为文件,而不是文本字符串.我还尝试使用awk以下变体:

history | tail -1 | awk '{ gsub("/[^0-9\*\ ]+", "") ; system( "echo" $1 ) }'

我确定我只是在正确地执行命令时遇到一些麻烦,但是一些帮助将不胜感激.

Mar*_*eed 7

您可以使用fc内置程序以编程方式访问历史记录.例如,我相信这会按照您的意愿行事:

alias _!='fc -e "sed -i -e \"s/^/sudo /\""'
Run Code Online (Sandbox Code Playgroud)

如果没有参数,fc("fix command"的缩写)会触发$EDITOR上一个命令并运行编辑结果.您可以使用该-e选项指定其他编辑器; 在这里,我sed将以命令的形式指定一个非交互式的命令,它将插入sudo命令行的前面.

该命令假设GNU sed.如上所述,它也适用于现代BSD/macOS上的版本,但是通过hackcident:它将for -e作为参数-i而不是新选项.因为-e只有一个表达式是可选的,所以这样可以正常工作,但这意味着在最后sed对临时文件进行备份-e,这将在命令完成后挂起.您可以在这些系统上使用此替代版本来使其更清洁:

alias _!='fc -e "sed -i \"\" -e \"s/^/sudo /\""'
Run Code Online (Sandbox Code Playgroud)

(这不适用于GNU sed,它将空字符串参数视为要操作的文件名...)

在较旧的系统上,更便携的解决方案可以使用ed:

alias _!="fc -e 'ed -s <<<$'\''s/^/sudo /\nw\nq'\'"
Run Code Online (Sandbox Code Playgroud)

你可以经常使用更简单的东西,例如sudo $(fc -ln -1)(-l= list命令,-n=没有数字,-1=只有最后一个命令),但通常你会遇到引用问题,因为命令是通过fc输入的方式输出的:

% touch '/etc/foo bar'
touch: /etc/foo bar: Permission denied
% sudo $(fc -ln -1)
touch: '/etc/foo: No such file or directory
Run Code Online (Sandbox Code Playgroud)

以上都不限于zsh,btw; fc发布到原始版本的ksh,所以它也适用于bash等.