Możliwe wyjaśnienie problemu
Myślę, że powodem, dlaczego :g/;/j
nie działa dlatego, że :g
komenda działa z algorytmem 2-pass:
- podczas pierwszego przejścia zaznacza linie zawierające wzór
;
- podczas drugiego przejścia działa na zaznaczonych liniach
Podczas drugiego przejścia :g
łączy linię 1;
z linią, 2;
ponieważ 1;
zostało zaznaczone podczas pierwszego przejścia. Podejrzewam jednak (nie jestem pewien), że nie łączy 1; 2;
się, 3;
ponieważ linia 2;
już nie istnieje, jej zawartość została scalona z linią, 1;
która została już przetworzona.
Więc :g
szuka następnej linii, która została zaznaczona podczas pierwszego przejścia ( 3;
) i łączy ją z następną ( 4;
). Następnie powtarza się problem, to nie może przyłączyć 3; 4;
się 5;
, ponieważ linia 4;
już nie istnieje.
Rozwiązanie 1 (z vimscript)
Być może możesz wywołać funkcję za każdym razem, gdy ;
zostanie znaleziony wiersz zawierający, aby sprawdzić, czy poprzedni wiersz zawiera również średnik:
function! JoinLines()
if getline(line('.')-1) =~ ';'
.-1join
endif
endfunction
Następnie użyj następującego polecenia globalnego:
:g/;/call JoinLines()
Lub bez funkcji:
:g/;/if getline(line('.')-1) =~ ';' | -j | endif
Rozwiązanie 2 (bez vimscript)
:g/;/.,/^[^;]*$/-1j
Ilekroć polecenie globalne :g
znajdzie wzorzec ;
, wykonuje polecenie: .,/^[^;]*$/-1j
Można go podzielić w następujący sposób:
:g/pattern/a,bj
Gdzie :
pattern = ;
a = . = number of current line
b = /^[^;]*$/-1 = number of next line without any semicolon minus one
b
można podzielić dalej w następujący sposób:
/ = 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
to skrócona forma polecenia Ex, :join
która podobnie jak większość innych poleceń Ex może być poprzedzona zakresem.
Tutaj poprzedza go zakres: .,/^[^;]*$/-1
( a,b
)
Zakres ma postać a,b
gdzie a
i b
są zwykle 2 numerami linii, i pozwala ci operować na grupie linii, których liczba jest pomiędzy a
i b
zamiast tylko jednej.
Tak więc j
polecenie łączy wszystkie linie między bieżącym ( a
) a następnym, który nie zawiera żadnego średnika minus jeden ( b
).
Aby uzyskać więcej informacji, zobacz:
:help :global
:help :join
:help :range
:g/;/j
nie działa, ponieważ odbywa się to w dwóch przebiegach: najpierw skanowany jest bufor, a następnie polecenie jest stosowane do pasujących linii.