I know that I can open a file through a pipe with vim with the following command:

cat myfile.txt | vim -

I also know that I can edit files on vim directly from the command line as the following:

vim -e myfile.txt -c ':%s/^/newstring-/g | x' 

The last command will open a file, execute a Vim command and close it. I'd like to mix these two things together, editing a file through a pipe and passing the file content to a bash variable. Something like the following:

var=$(cat myfile.txt | vim - -e -c ':%s/^/newstring-/g | x')

Well, this last command doesn't work at all. It's just an example to represent the idea. Is it possible to do something like this with vim? Or I better off just write the content of my changes on a new file and then accessing that new file from the shell as the following:

vim -e myfile.txt -c ':execute "%s/^/newstring-/g | normal :wq! newfile.txt\<Enter>"'

This last command works fine... But I'd like to know if there's a more direct way of storing inside a variable the changes that I make with vim.


I found a solution to this issue on this answer from StackOverflow. The following line does what I expected in my question:

var=$(cat myfile.txt | vim -e -c ':g/./normal osleep 0.5' '+%p' -escq! /dev/stdin)

Honestly, I don't fully understand the syntax '+%p' -escq! /dev/stdin... But adding it on the pipe works to continue pipping values through Vim.

  • 1
    The +%p adds a command to print the whole buffer. The last bit is three different flags (e,s,c), of which you may only need c (though es is a good idea when doing this kind of thing). The q! is then an argument to c, so quit with no warnings. Lastly, you have the filename (in this case, the special file for standard in) – D. Ben Knoble Apr 24 at 11:43

:xit is supposed to save file to disk, not write it to stdout. You're strongly advised to use sed for scripting instead of vim.

  • Sorry, I think my question wasn't very clea and there's a misunderstanding on what I'd like to do... In this case, I'd have to write vim output to stdout in order to save it inside a bash variable, no? – raylight Apr 22 at 18:31
  • @raylight What you'd like to do != what you really do. – Matt Apr 22 at 18:34
  • What do you mean? – raylight Apr 22 at 18:34
  • @raylight In order to write buffer to stdout you must say to vim to write it to stdout and not to write it on disk. Isn't it clear? – Matt Apr 22 at 18:39

I strongly believe that the right answer to this question is: don't do it.

Vim is an interactive program and you will fight to bent it to your needs when the right bash command will be much easier and more efficient:

echo 'abcde' > file
result=$(cat file | sed -e 's/a/x/' -e 's/bc/BC/')
echo $result  # xBCde

Sed is a very powerful tool, man sed is a good starting point but there are a lot of resources online to get started. Here we simply pass several substitution commands which you probably already are familiar with because they work the same way as vim's :s

  • Actually, that was just an example... I know that I can use sed, grep and awk to solve many problems. They're great when my problems are simple ones. However, on vim I have global commands... Things like :g/expression/normal $F'D. Many times I can easily solve something with a global command that I'd have to struggle a lot to solve with sed or awk... So I'm considering the idea of easily solving small problems with vim instead of worrying a lot with small details of sed and awk. They can get complicated very fast when the task we do is not an ordinary one. – raylight Apr 22 at 18:27
  • :g is used to apply a command to a pattern like you can do with sed sed "/expression/s/'.*// Given how versatile sed is and how powerful awk this will most probably be easier :) – statox Apr 22 at 18:38
  • sed is limited to work in one like at a time... With :g I can go to different lines. Don't get me wrong here. I know sed is a great tool. But in my daily life many times I get myself easily solving problems with :g which would require a considerable amount of time for me to solve with sed or awk... When I can solve with the command line I do it. But when I don't see a clear way of doing it on the command line and I can easily solve with :g, I'd like to have the command for that as an alternative. – raylight Apr 22 at 18:43
  • I'm not convinced but I get your point :) I think it will be hard to find a convenient way to do what you want, but I'm curious to see the answers :) – statox Apr 22 at 18:48

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.