vim如何“用sudo写作”技巧工作?

你们许多人可能已经看到了允许你在需要root权限的文件上写命令,即使你忘记用sudo打开vim:

:w !sudo tee % 

事情是,我没有得到这里发生的事情。

我已经想到了这个: w是为了这个

  *:w_c* *:write_c* :[range]w[rite] [++opt] !{cmd} Execute {cmd} with [range] lines as standard input (note the space in front of the '!'). {cmd} is executed like with ":!{cmd}", any '!' is replaced with the previous command |:!|. 

所以它通过所有的行作为标准input。

!sudo tee部分以pipe理员权限调用tee

为了让所有人理解, %应该输出文件名(作为tee一个参数),但是我找不到对这种行为的帮助。

有人能帮我剖析这个命令吗?

%表示“当前文件”

正如eugene y指出的那样 , %确实意味着“当前的文件名”。 Vim的另一个用途是替代命令。 例如, :%s/foo/bar意思是“ 在当前文件中 ,用barreplacefoo出现次数”。 如果在键入:s之前突出显示某些文本,则会看到突出显示的行代替%作为替代范围。

:w不更新您的文件

这个诀窍的一个令人困惑的部分是,你可能会认为:w正在修改你的文件,但事实并非如此。 如果你打开并修改file1.txt ,然后运行:w file2.txt ,那将是一个“另存为”; file1.txt不会被修改,但是当前的缓冲区内容将被发送到file2.txt

您可以使用shell命令替代 file2.txt 来接收缓冲区内容 。 例如:w !cat只显示内容。

如果Vim没有使用sudo访问,那么它的:w不能修改受保护的文件,但是如果它将缓冲区内容传递给shell,shell中的命令可以使用sudo运行 。 在这种情况下,我们使用tee

了解三通

至于tee ,在正常的输气pipe道情况下,将tee命令描述为T形pipe道:将输出指向指定的文件, 并将其发送到标准输出 ,这可以通过下一个pipe道命令捕获。

例如,在ps -ax | tee processes.txt | grep 'foo' ps -ax | tee processes.txt | grep 'foo' ps -ax | tee processes.txt | grep 'foo' ,进程列表将被写入一个文本文件传递给grep

  +-----------+ tee +------------+ | | -------- | | | ps -ax | -------- | grep 'foo' | | | || | | +-----------+ || +------------+ || +---------------+ | | | processes.txt | | | +---------------+ 

(用Asciiflow创build的图表 )

有关更多信息,请参阅tee手册页 。

三通作为黑客

在你的问题描述的情况下, 使用tee是一个黑客,因为我们忽略了它的一半sudo tee写入我们的文件,并将缓冲区内容发送到标准输出,但我们忽略标准输出 。 在这种情况下,我们不需要把任何东西传递给另一个pipe道命令。 我们只是使用tee作为编写文件的替代方式,所以我们可以使用sudo来调用它。

使这个窍门容易

你可以将这个添加到你的.vimrc ,使这个技巧易于使用:只需input:w!!

 " Allow saving of files as sudo when I forgot to start vim using sudo. cmap w!! w !sudo tee > /dev/null % 

> /dev/null部分明确抛出标准输出,因为正如我所说的,我们不需要传递任何东西到另一个pipe道命令。

在执行的命令行中, %代表当前的文件名 。 这logging在:help cmdline-special

 In Ex commands, at places where a file name can be used, the following characters have a special meaning. % Is replaced with the current file name. 

正如你已经发现的那样, :w !cmd将当前缓冲区的内容传送给另一个命令。 tee所做的就是将标准input复制到一个或多个文件,也复制到标准输出。 因此, :w !sudo tee % > /dev/null有效地将当前缓冲区的内容作为根文件写入当前文件。 另一个可用于此的命令是dd

 :w !sudo dd of=% > /dev/null 

作为一个捷径,你可以将这个映射添加到你的.vimrc

 " Force saving files that require root permission cnoremap w!! w !sudo tee > /dev/null % 

用上面的命令可以input:w!!<Enter>以root身份保存文件。

:w – 写一个文件。

!sudo – 调用shell sudo命令。

tee – 使用teeredirect的write(vim:w)命令的输出。 %只不过是当前文件名,例如/etc/apache2/conf.d/mediawiki.conf。 换句话说,tee命令是以root身份运行的,它需要标准input并将其写入由%表示的文件。 但是,这将提示重新加载文件(点击L加载vim中的更改本身):

教程链接

这也很好:

 :w !sudo sh -c "cat > %" 

这是由@Nathan Long的评论所启发的。

注意

"必须用来代替'因为我们希望%在传递到shell之前被扩展。