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
意思是“ 在当前文件中 ,用bar
replacefoo
出现次数”。 如果在键入: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之前被扩展。