Possible explanation of the problem
I think the reason why
:g/;/j doesn't work is because the
:g command operates with a 2-pass algorithm:
- during the first pass it marks the lines containing the pattern
- during the second pass it operates on the marked lines
During the second pass,
:g joins the line
1; with line
1; was marked during the first pass.
However I suspect (not sure) that it doesn't join
1; 2; with
3; because the line
2; doesn't exist anymore, its content has been merged with the line
1; which has already been processed.
:g looks for the next line which was marked during first pass (
3;) and joins it with the following one (
4;). After that the problem repeats, it can't join
3; 4; with
5; because the line
4; doesn't exist anymore.
Solution 1 (with vimscript)
Maybe you could call a function whenever a line containing
; is found to check whether the previous line also contains a semicolon:
if getline(line('.')-1) =~ ';'
Then use the following global command:
Or without a function:
:g/;/if getline(line('.')-1) =~ ';' | -j | endif
Solution 2 (without vimscript)
Whenever the global command
:g finds the pattern
; it executes the command:
It can be broken down like this:
pattern = ;
a = . = number of current line
b = /^[^;]*$/-1 = number of next line without any semicolon minus one
b can be broken down further like this:
/ = look for the number of the next line matching the following pattern
^ = a beginning of line
[^;] = then any character except a semicolon
* = the last character can be repeated 0 or more times
$ = an end of line
/ = end of pattern
-1 = removes one to the number you just got
j is the abbreviated form of the Ex command
:join which like most other Ex commands can be preceded by a range.
Here it's preceded by the range:
A range follows the form
b are generally 2 line numbers, and allows you to operate on a group of lines whose number is between
b, instead of just one.
j command joins all the lines between the current one (
a) and the next one which doesn't contain any semicolon minus one (
For more information, see:
:g/;/jdoesn't work because it is done in two passes: first the buffer is scanned, then the command is applied to the matching lines.