Chciałbym łączyć linie tylko dla linii, które mają określony wzór (np. ;
), Jednak przy użyciu g/;/j
nie działa zgodnie z oczekiwaniami, chyba że zostanie wywołany kilka razy.
Na przykład następująca treść:
a
1;
2;
3;
4;
5;
b
6;
7;
8;
9;
c
przy użyciu: :g/;/j
dane wyjściowe to:
a
1; 2;
3; 4;
5; b
6; 7;
8; 9;
c
lub :g/;/-j
daje:
a 1; 2; 3; 4; 5;
b 6; 7; 8; 9;
c
Podobnie jest z: :g/;\_.\{-};/j
.
Moje oczekiwane wyniki to:
a
1; 2; 3; 4; 5;
b
6; 7; 8; 9;
c
lub coś podobnego, więc wszystkie linie zawierające wzór są ze sobą połączone.
Jak można to osiągnąć?
global-command
kenorb
źródło
źródło
: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.Odpowiedzi:
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 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 łączy1; 2;
się,3;
ponieważ linia2;
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ż linia4;
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:Następnie użyj następującego polecenia globalnego:
Lub bez funkcji:
Rozwiązanie 2 (bez vimscript)
Ilekroć polecenie globalne
:g
znajdzie wzorzec;
, wykonuje polecenie:.,/^[^;]*$/-1j
Można go podzielić w następujący sposób:
Gdzie :
b
można podzielić dalej w następujący sposób: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
gdziea
ib
są zwykle 2 numerami linii, i pozwala ci operować na grupie linii, których liczba jest pomiędzya
ib
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:
źródło
Cały czas robię podobne łączenie za pomocą globalnego wyszukiwania i zastępuję:
\n
pasuje do nowej linii.Aby znaleźć i usunąć puste linie:
Nie jestem pewien dlaczego, ale jeśli chcesz wstawić nową linię, musisz użyć
\r
źródło
s
sam będzie działać tylko na jednej linii, aby to globalny, trzeba użyć%s
, ale to będzie dołączyć niemal wszystkie linie, w tym spoza;
linii:s
polecenia dokładnie do tego, co chcesz. Myślę, że to%s/;\n\(.*;\)\@=/;/
robi to, czego potrzebujesz.