Możliwe wyjaśnienie problemu
Myślę, że powodem, dlaczego :g/;/jnie działa dlatego, że :gkomenda 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 :gszuka 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 :gznajdzie 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
jto skrócona forma polecenia Ex, :joinktóra podobnie jak większość innych poleceń Ex może być poprzedzona zakresem.
Tutaj poprzedza go zakres: .,/^[^;]*$/-1( a,b)
Zakres ma postać a,bgdzie ai bsą zwykle 2 numerami linii, i pozwala ci operować na grupie linii, których liczba jest pomiędzy ai bzamiast tylko jednej.
Tak więc jpolecenie łą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/;/jnie działa, ponieważ odbywa się to w dwóch przebiegach: najpierw skanowany jest bufor, a następnie polecenie jest stosowane do pasujących linii.