5

Fully realizing the heritage of vi, I know that its predecessor (ex) could be, and was, used for command line processing of files ("sed-style", if you like).

The manpage says:

-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).

And:

-e

Start Vim in Ex mode, just like the executable was called "ex".

But I was unable to find "real-life" examples, or get something like a simple search-and-replace to work myself. I like examples...

So let's assume a file.txt...

abcdef

...and I would like to open that file, remove all occurrences of e in it (:%s/e//g if I were in full vim mode), save, and close.

How would I go about it?

1

2 Answers 2

6

An "ex command" means anything that you type in the commandline after the :, such as :write, it doesn't really have anything to do with "ex mode", as such. ex mode is a "mode" where you only have the commandline, and not the graphical editor ("vi" stands for "visual ex mode").

So it's really as simple as:

vim -c ':%s/e//g' -c ':wq' file.txt

There's no need to use "ex mode". You can if you want:

vim -e -c ':%s/e//g' -c ':wq' file.txt

It has the advantage of not messing with your terminal so much, but other than that there's little difference.

3
  • And at this point I wonder what I did wrong, because I am sure I tried just that. Well, gotta check the command history on the office system tomorrow. :-D Cheers, and thanks!
    – DevSolar
    Oct 26, 2015 at 17:47
  • 4
    I think using -es is more performant, I have noticed a small "blink" without it as Vim started up and quit.
    – muru
    Oct 28, 2015 at 16:16
  • @muru, I don't know if that's performance so much as the fact that -s will make ex silent.
    – Wildcard
    Oct 31, 2016 at 7:31
5

Update:

The easiest portable way to do this is:

printf '%s\n' %s/e//g x | ex file

This avoids error conditions discussed below.


Original Answer

One of the advantages of ex as opposed to Vim is that ex is guaranteed by POSIX.

If you're in the sysadmin world and you need to script automated edits to text files (e.g. configuration files to be edited across thousands of different remote servers), you want to use something portable. Perl is great but not portable—and it's overkill for very simple file edits. sed and awk are both guaranteed by POSIX, but they're not designed for in-place file editing. (sed has a -i switch in some implementations such as GNU sed to allow for in-place file editing, but for portable scripting that option shouldn't be relied upon as it is not in the POSIX standard for sed.)

The correct tool for the job is ex.

For your example, removing all instances of the letter "e" from the file, the ex command is simple (and portable):

ex -sc '%s/e//g | x' file

The -s switch starts ex silently, for batch processing (as opposed to interactive use where messages are printed out to the terminal).

The -c switch precedes the command to be run.

The substitute command is as you wrote it.

The vertical bar separates commands to be run sequentially (unless you're using it with the global command, but we're not.)

The x command exits after writing any changes to the file. (It only writes to the file if edits were made, thus preserving the file's timestamp if no edits were necessary.)


There is one major caveat to the above command: If the letter "e" doesn't exist anywhere in the file, the substitute command will fail and the x command won't be executed. This will leave you staring at a silently running ex process with no error output, or output of any kind. It's not at all obvious in this case what's happening, but it's actually waiting for you to type in ex commands. (It's more obvious if you omit the -s flag, so that you are actually prompted for input with a colon.) Just type q! to exit in this case.

If I were to actually use this to edit files on remote servers, of course, I would want the command to exit correctly even if there weren't any instances of the letter "e" in the files being edited. Vim has an e flag for the substitute command which would handle this by suppressing errors if the regex weren't matched:

ex -sc '%s/e//ge | x' file

But the POSIX way would be to use the global command to run the substitute command on all lines matching the given regex—and to not run substitute at all if the regex weren't found:

ex -sc 'g/e/s///g
x' file
5
  • But what if the platform you are using Vim on is not POSIX (and therefore doesn't have ex)? ;-) (Just pulling your leg, good answer.)
    – DevSolar
    Jan 25, 2016 at 10:35
  • Shouldn't the last example be ex -sc 'g/e/s///g | x' file?
    – Timm
    Jun 22, 2016 at 15:20
  • @Timm, nope. See for yourself—using | in a global command just adds to the command which is executed for every matching line. So after the first line gets the substitution performed, the x command would run, causing the editor to exit. You can get around this by embedding a newline, or (my preferred method) you can use printf to pipe the commands to ex.
    – Wildcard
    Jun 23, 2016 at 5:13
  • @Wildcard, can you show how you use printf in this example? Thanks!
    – Timm
    Jun 24, 2016 at 7:14
  • @Timm, I already edited it in at the top of the answer. ;)
    – Wildcard
    Jun 24, 2016 at 7:39

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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