Command ex is the non-visual form of vi (specified by POSIX). Any command used in vi in command mode (command following :) can be kept in a file for scripting against the text.

Use case

You have a huge file with text, which you want to query a database using the inner query. For example, you have a file like below

# for demo, generating 5K random numbers
seq 1 5000 | xargs -n 1 bash -c 'echo $RANDOM' > /tmp/sample.txt

# below is what file contains
head /tmp/sample.txt
8388
2758
29338
10218
16656
11292
31976
22647
21912
5451

To query a database using an inner query, you need something like the below, where quotes surround every item, separated by a comma, join every 1000 lines and finally surround them using brackets so that you can use each line in the IN clause of select query.

Note: In Oracle, 1000 is the limit for IN clause.

('8388', '2758', ...)
('21290', '27447', ...)
('26700', '11077', ...)
('3547', '13076', ...)
('10770', '26768', ...)
('10893', '24271', '6445', '4207', '18479')

Solution

Below are the steps to accomplish the above. Put the below commands in a file (I will explain what each will do later)

$ cat /tmp/format

%s/\(^.*$\)/'\1',/g
g/^/j999
%s/,$//g
%s/\(^.*$\)/(\1)/g
x

Now run above /tmp/format against /tmp/sample.txt file using ex command.

cat /tmp/format | ex /tmp/sample.txt

And voila, /tmp/sample.txt will have the format we are looking for.

Note: You can run above commands one by one, in Vi using command mode (:), you will get same result

Explanation

  • Souround each line item with quotes and end the line with , - %s/\(^.*$\)/'\1',/g, below is how it looks after this command. (Check this post to know more about regex backreference)
      '8388', 
      '2758',
      ...
      '18479',
    
  • Join every 999 lines - g/^/j999, below is how it looks
      '8388', '2758', ... ,
      '21290', '27447', ... , 
      '26700', '11077', ... ,
      '3547', '13076', ... ,
      '10770', '26768', ... ,
      '10893', '24271', '6445', '4207', '18479', 
    
  • Remove the , at end of line - %s/,$//g
      '8388', '2758', ... 
      '21290', '27447', ... 
      '26700', '11077', ... 
      '3547', '13076', ... 
      '10770', '26768', ... 
      '10893', '24271', '6445', '4207', '18479'
    
  • Souround each line with brackets () - %s/\(^.*$\)/(\1)/g
      ('8388', '2758', ...)
      ('21290', '27447', ...)
      ('26700', '11077', ...)
      ('3547', '13076', ...)
      ('10770', '26768', ...)
      ('10893', '24271', '6445', '4207', '18479')
    
  • Exit x

Here is the sample file used - sample.txt and here is the final result after applying ex - sample_result.txt.

Above is one example of how you can use ex to execute multiple commands to manipulate text. You can use more complex commands, and you don’t need to run them one by one in Vi.

– RC