Scripting Vim from the Command Line

One of the more powerful features of Vim is its ability to perform edits to text in a scripted way.

If you view the man page for Vim, there’s an entry for the -c argument that looks like this:

-c {command}
   {command} will be executed after the first file has been read.  
   {command} is interpreted as an Ex command.  If the  {command}  
   contains spaces it must be enclosed in double quotes (this 
   depends on the shell that is used).  Example: Vim "+set si" main.c
   Note: You can use up to 10 "+" or "-c" commands.

That part about Ex command is key — these are the commands that are executed when we type the colon in Vim.

But how do we go from a man page entry to something useful? How about a case study.

Manually Removing Wordfence Tables from a SQL Dump

Let’s say that the Wordfence plugin was exporting data in a binary form which was breaking things when trying to import the database into a new environment. They know about this, and have this helpful guide:

That’s a fine solution if you have the site up and running, but suppose you have a bunch of sql files that need to be cleaned up so that they can be imported cleanly.

After cleaning up those files manually a few times with Vim, you’ll find that you will be doing a number of common motions like searching, deleting, and saving those files. At a certain point, you might even realize that you can us the global ex command to “do stuff” on each line that matches a regex.

For me, when working through the cleanup process of Wordfence from SQL files, that process generally looked like this:

  1. Search the SQL file using the “very magic” setting. This might take some fiddling so that the regex gets the lines that you want. The specific keystrokes might look like:
    • /\vsearch_regex
  2. Using the “global print” ex command with an empty search string (to re-use the last search), do a quick sanity check to make sure the correct lines are being hit. Those keystrokes might look like:
    • :g//p
  3. Use the “global normal” ex command to execute the normal (as in “normal mode”) keystrokes for every matched line. What this means is that we can do something like “delete the next four paragraphs for each match.” This is helpful in the SQL files that I was working with because each “paragraph” was a block of SQL statements — both definitions as well as data. The keystrokes for that might look like:
    • :g//normal 4dap

Those steps are all very abstract, so here’s a screencast working through that process of cleaning up those Wordfence tables:

Automating Vim From a Shell Script

The above steps are great at doing advanced editing during a session, but returning to the goal of actually automating that editing, you’ll want to make use of that -c flag that we mentioned earlier.

As a concrete example, that process of removing Wordfence tables from a SQL file could be abstracted even more. In this case, I created a shell script that:

  1. Emptied out a register (in this case the @t register)
  2. Do some “normal” keystrokes on lines matching \v_wf.{-}
  3. Save the edited file
  4. Create a new buffer and paste the contents of the @t buffer into this new buffer

Here’s the actual script that I ended up using to process those SQL files:

vim -c 'let @t=""' \
   -c ':g/\v_wf.{-}`/normal "Tyapdap' \
   -c ":sav $file" \
   -c ':new wf-tables.sql.bak | :normal "tp' \
   -c ':wa | :qa' \