9

I would like to write whole buffer into standard output (/dev/stdout) instead of the file and the following command works as expected while editing the file:

:w >> /dev/stdout

Hint: Press Control+L to refresh the screen.

But it doesn't work as expected when I'm trying to do the same from the command line (non-interactively), in example:

$ echo This is example. | vim - '+:w >> /dev/stdout' '+:q!'
Vim: Reading from stdin...

The same with :w !tee, :x! /dev/stdout, :%print and similar.

Before quit, it's saying: [Device] 1L, 17C appended.

Is there any way of forcing vim to write the standard input into standard output in the middle of a pipe? Maybe it's somehow buffered?

  • 4
    Just curious, what are you trying to accomplish? As in, what will vim do for you here that some other tool might not? – Jay Thompson Feb 14 '15 at 17:32
  • @JayThompson I'm trying to use vim for file parsing instead of sed (e.g. mass repeated complex changes to multiple large files). The example doesn't do anything to keep it simple and not making potential duplicate of another post. – kenorb Feb 14 '15 at 17:37
  • You know about vipe, so any reason you're not using it? – muru Feb 14 '15 at 17:51
  • @muru I didn't use it yet, not much documentation available and it's off-topic here. – kenorb Feb 14 '15 at 17:53
  • Questions about vipe might be, but there's no reason it can't be the answer. So I am wondering why I shouldn't post it as an answer. – muru Feb 14 '15 at 17:56
9

To print buffer to shell standard output, vim needs to start in Ex mode, otherwise it'll open "normal" way with its own window and clear any output buffers on quit.

Here is the simplest working example:

$ echo foo | vim -e '+%print' '+q!' /dev/stdin
foo

or even shorter:

$ echo foo | ex +%p -cq! /dev/stdin
$ echo foo | ex +"%p|q!" /dev/stdin

Note: The command vim -e is basically equivalent to ex command.

Special file descriptor to standard input needs to be specified (/dev/stdin) in order to prevent extra annoying messages (as explained below).


And here are some examples with parsing strings:

$ echo This is example. | vim -e '+s/example/test/g' '+%print' '+q!' /dev/stdin
This is test.
$ echo This is example. | vim - -es '+s/example/test/g' '+%print' '+q!'
Vim: Reading from stdin...
This is test.

Note: The last example shows extra annoying message which is not possible to hide it, it's because a standard strategy of reading the whole file into memory and saying it was read from the standard input. The first example works without the message, because the file produce endless data without an end-of-file (EOF) signal, so it'll will never reach the end of its input reading.


Related:

  • 1
    You can just do +q! rather than +:q!, right? – Andrew MacFie Jul 28 '17 at 20:20
  • @AndrewMacFie It's same thing, updated, thanks. – kenorb Jul 28 '17 at 22:29
3

vipe is a convenient tool for editing pipelines, part of the moreutils package. It is a wrapper for editors (including the vi which gives it its name). It uses the EDITOR environment variable to set the editor, so, like with other tools that make use of EDITOR (such as crontab, visudo, etc.), you can script actions using that variable. For example, you can change it to do:

$ echo foo | EDITOR='vim +:s/foo/bar/ +wq' vipe | tail
bar

Of course, complicated actions might devolve to quoting hell, so you could write a script:

#! /bin/sh

vim "+:s/foo/bar" '+wq' "$@"

And use EDITOR="sh /path/to/script".

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.