vim如何“用sudo写"?把戏? [英] How does the vim "write with sudo" trick work?

查看:22
本文介绍了vim如何“用sudo写"?把戏?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

:w !sudo tee %

问题是我不明白这里到底发生了什么.

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

 *:w_c* *:write_c*:[range]w[rite] [++opt] !{cmd}使用 [range] 行作为标准输入执行 {cmd}(注意!"前面的空格).{cmd} 是像 ":!{cmd}" 一样执行,任何 '!'被替换为上一个命令 |:!|.

因此它将所有行作为标准输入传递.

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

为了使所有人都有意义,% 应该输出文件名(作为 tee 的参数),但我找不到有关此行为的帮助的参考.

tl;dr 谁能帮我剖析一下这个命令?

解决方案

In :w !sudo tee %...

% 表示当前文件"

正如 eugene y 指出的% 确实表示当前文件名",它被传递给 tee 以便它知道要覆盖哪个文件.

(在替换命令中,它略有不同;正如 :help :% 所示,它 等于 1,$(整个文件)(感谢 @Orafu指出这不会对文件名求值.例如,:%s/foo/bar 表示在当前文件中,替换出现的 foo with bar."如果在键入 :s 之前突出显示某些文本,您将看到突出显示的行代替了 % 作为您的替换范围.)

:w 没有更新您的文件

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

代替file2.txt,您可以替换一个shell 命令来接收缓冲区内容.例如, :w !cat 只会显示内容.

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

了解三通

对于tee,将tee命令想象成正常bash管道情况下的T形管道:它将输出定向到指定的文件和也将它发送到标准输出,它可以被下一个管道命令捕获.

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

 +-----------+ tee +------------+||-------- |||ps -ax |-------- |grep 'foo' |||||||+-----------+ ||+------------+||+--------------+|||进程.txt |||+--------------+

(使用 Asciiflow 创建的图表.)

有关详细信息,请参阅 tee 手册页.>

T恤作为一个黑客

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

让这个技巧变得简单

您可以将其添加到您的 .vimrc 中,以使这个技巧易于使用:只需键入 :w!!.

" 当我忘记使用 sudo 启动 vim 时,允许将文件保存为 sudo.cmap w!!w !sudo tee >/开发/空%

<代码>>/dev/null 部分明确丢弃标准输出,因为正如我所说,我们不需要将任何内容传递给另一个管道命令.

Many of you have probably seen the command that allows you to write on a file that needs root permission, even when you forgot to open vim with sudo:

:w !sudo tee %

The thing is that I don't get what is exactly happening here.

I have already figured this: w is for this

                                                        *: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 |:!|.

so it passes all the lines as standard input.

The !sudo tee part calls tee with administrator privileges.

For all to make sense, the % should output the filename (as a parameter for tee), but I can't find references on the help for this behavior.

tl;dr Could someone help me dissect this command?

解决方案

In :w !sudo tee %...

% means "the current file"

As eugene y pointed out, % does indeed mean "the current file name", which is passed to tee so that it knows which file to overwrite.

(In substitution commands, it's slightly different; as :help :% shows, it's equal to 1,$ (the entire file) (thanks to @Orafu for pointing out that this does not evaluate to the filename). For example, :%s/foo/bar means "in the current file, replace occurrences of foo with bar." If you highlight some text before typing :s, you'll see that the highlighted lines take the place of % as your substitution range.)

:w isn't updating your file

One confusing part of this trick is that you might think :w is modifying your file, but it isn't. If you opened and modified file1.txt, then ran :w file2.txt, it would be a "save as"; file1.txt wouldn't be modified, but the current buffer contents would be sent to file2.txt.

Instead of file2.txt, you can substitute a shell command to receive the buffer contents. For instance, :w !cat will just display the contents.

If Vim wasn't run with sudo access, its :w can't modify a protected file, but if it passes the buffer contents to the shell, a command in the shell can be run with sudo. In this case, we use tee.

Understanding tee

As for tee, picture the tee command as a T-shaped pipe in a normal bash piping situation: it directs output to specified file(s) and also sends it to standard output, which can be captured by the next piped command.

For example, in ps -ax | tee processes.txt | grep 'foo', the list of processes will be written to a text file and passed along to grep.

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

(Diagram created with Asciiflow.)

See the tee man page for more info.

Tee as a hack

In the situation your question describes, using tee is a hack because we're ignoring half of what it does. sudo tee writes to our file and also sends the buffer contents to standard output, but we ignore standard output. We don't need to pass anything to another piped command in this case; we're just using tee as an alternate way of writing a file and so that we can call it with sudo.

Making this trick easy

You can add this to your .vimrc to make this trick easy-to-use: just type :w!!.

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

The > /dev/null part explicitly throws away the standard output, since, as I said, we don't need to pass anything to another piped command.

这篇关于vim如何“用sudo写"?把戏?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆