73

I'm using grep -e Peugeot -e PeuGeot carlist.txt to search through carlist.txt and pull out some items and I presumed that grep -e Peugeot -e PeuGeot carlist.txt | vi would pipe it through for me but this is what I get:

Vim: Warning: Input is not from a terminal
Vim: Error reading input, exiting...
Vim: preserving files...
Vim: Finished.
Jeff Schaller
  • 66,199
  • 35
  • 114
  • 250
Lmedza
  • 731
  • 1
  • 5
  • 3
  • if you want to include it in a file, I'd first use vi on the file, and then : `:read !grep -e Peugeot -e PeuGeot carlist.txt` . `:read !cmd...` will include the output of cmd... in the file (at the cursor's location) – Olivier Dulac Nov 21 '13 at 17:13
  • It's not clear what you mean by a "vi file". If you want the output to go into a file, use `grep ... > /tmp/foo`. You can add `&& vi /tmp/foo` on the end if you want to edit that file immediately. – LarsH Nov 21 '13 at 18:29
  • 1
    In fact there's no such thing as a "vi file". `vi` operates on arbitrary text files; the files themselves are not directly associated with `vi`. (Or, as I just learned, `vi -` will cause `vi` to operate on the contents of `stdin`; `vim` does this, but not all versions of `vi` do.) – Keith Thompson Nov 21 '13 at 19:45
  • Related: [How to edit content from the standard input?](http://vi.stackexchange.com/q/737/467) at Vim SE – kenorb Feb 19 '15 at 13:06

6 Answers6

128

Running vi or vim with '-' as an argument makes it read the file to edit from standard input. Hence:

grep -e Peugeot -e PeuGeot carlist.txt | vi -

will do what you need.

Petr Uzel
  • 7,157
  • 4
  • 30
  • 26
  • 4
    For anyone seeing this, attention: it expects from `stdin`. In some cases you'll have to redirect from `stderr` to `stdin`, e.g: `valgrind my_file.out 2>&1 | vi -` – Ciro Costa Sep 30 '15 at 03:08
  • This removes search highlightings – MD. Mohiuddin Ahmed Nov 06 '16 at 09:28
  • 6
    @MD.MohiuddinAhmed, how do you expect to keep `grep`'s search coloring (composed of nonprintable characters) inside of Vim? You can always just do a search *in* Vim. – Wildcard Nov 15 '16 at 06:25
  • I thought we can go with http://www.vim.org/scripts/script.php?script_id=302 plugin within vim. – MD. Mohiuddin Ahmed Nov 15 '16 at 13:20
  • This answer is not quite accurate. You are piping to vim here, not vi. vi does not accept stdin. You can confirm it is vim by opening your "vi" and then :version – Kajukenbo Oct 13 '21 at 01:23
16

Apart of vim -, you can also use process substitution using the <(command) syntax, in example:

vim <(echo This is example.)
vim <(cat /etc/hosts)

See also:

kenorb
  • 20,250
  • 14
  • 140
  • 164
12

You should use output redirection:

grep ... > newfile.txt && vi newfile.txt

Also, I think your grep can be improved:

grep 'Peu[gG]eot' carlist.txt > newfile.txt && vi newfile.txt
Joseph R.
  • 38,849
  • 7
  • 107
  • 143
6

Output redirection can also be used like this:

vi <(grep ...)

Even multiple command outputs can be redirected, as if they were saved in separate files:

vim -d <(ls) <(ls -a)
musa
  • 1,018
  • 2
  • 10
  • 18
1

In ~/bin/r:

#!/bin/sh
[ $# -eq 0 ] && set -- -;
exec vi -R "$@"

in ~/.vimrc:

:  au StdinReadPost * set buftype=nofile

Then:

ls |r
grep -e Peugeot -e PeuGeot carlist.txt | r

and I've got

r- () { "$@" | r; }

in my ~/.bashrc, so

r- ls -l
jthill
  • 2,671
  • 12
  • 15
0

There are many effective ways to do what you want, either within vi(m) or outside vi(m).

Run your command, produce a (temporary) file, then edit the file (see Joseph R.'s answer)

grep -e"Peu[gG]eot" carlist.txt && vi /tmp/peugeot.txt

Run your command (in the background) to produce a temporary file, and edit the file, using ":e!" to refresh your file as it is produced (this is useful for logfiles, and other files being produced by another process, e.g. cron?),

grep -e "Peu[gG]eot" carlist.txt > /tmp/peugeot.txt &
vi /tmp/peugeot.txt

Run vi(m), and run a child process to create the temporary file, and then read it,

vi
:!grep -e "Peu[gG]eot" carlist.txt > /tmp/peugeot.txt
:r /tmp/peugeot.txt

Or, just switch to the file,

:e /tmp/peugeot.txt

Run vi(m), and use the double-bang "!!" to have vi run the child command, taking the results and inserting them into the current location (overwrites the current line, so make sure you have a blank line),

vi
i
here
empty
there
<esc>
kk
!!grep -e "Peu[gG]eot" carlist.txt

And now you can write the file (if you want to) to any filename,

:w /tmp/someotherfilename.txt

And Petr Uzel's answer is also good,

grep -e "Peu[gG]eot" carlist.txt | vi -

Which reads from stdin

ChuckCottrill
  • 1,027
  • 1
  • 11
  • 15