Odpowiedzi:
Polecenie Vima: g jest przeznaczone właśnie do tego rodzaju zadań; uruchomienie pojedynczej akcji na każdej linii, która pasuje do określonego wzorca. Oto moja odpowiedź:
:g/.\n\n\@!/norm o
Wzór, którego używam to /.\n\n\@!/
. Podział na części składowe:
.
Dopasowuje dowolny znak w linii. (służy do natychmiastowego odrzucenia wszelkich istniejących pustych linii z analizy)\n
Odpowiada pojedynczemu \ n na końcu powyższego znaku\n\@!
Nie powiedzie się, jeśli jest inny \ n zaraz po wcześniejszym \ n.(Sprawdź :h E59
więcej informacji o \@!
podobnych specyfikacjach dopasowania w wyrażeniach regularnych - jest też kilka innych!)
Zatem wyrażenie regularne polecenia: g wybrało teraz każdą niepustą linię, która kończy się pojedynczą nową linią, a po której nie następuje pusta linia.
Po wzorcu w :g
instrukcji pojawia się polecenie uruchomienia na pasujących liniach. W tym przypadku kazałem mu wykonać polecenie w trybie normalnym (w skrócie norm
), a polecenie do uruchomienia jest po prostu o
, które wstawia pustą linię poniżej bieżącej linii.
Podsumowując, polecenie znajduje każdą linię, która nie ma pustej linii pod nią, i dodaje jedną. I to wszystko! Możesz zajrzeć do artykułu Power of G na vim wiki, gdzie znajdziesz więcej wymyślnych rzeczy, które możesz zrobić :g
(i jest to negatywna siostra :v
) - to jedno z tych niesamowicie użytecznych poleceń, na których wkrótce będziesz polegać, a następnie strasznie przegapisz w edytorach które tego nie mają.
:%s/$/
, a następnie naciśnij ^V
, a następnie naciśnij Enter
.
:%s/$/<C-V><CR><CR>
(używać typowego kodowania klawiszy vim-folk), takie podejście po prostu dodaje nową linię po każdej linii. Oznacza to, że linie, które są już oddzielone spacjami (patrz Linia 3 -> Linia 4, w tekście przykładowym), kończą się otrzymywaniem dodatkowych pustych linii. Pierwotnym pytaniem było uniknięcie dodawania dodatkowych pustych linii tam, gdzie już istniały w tekście początkowym.
Kiedy testowałem globalne wyszukiwanie @ NeilForester i zastępuję odpowiedź, stwierdziłem, że nie trafiło co sekundę zamierzonej zamiany w kolejnych niepustych liniach, jeśli linie miały tylko jeden znak w każdym. Wydaje się, że jest to spowodowane tym, że wzór zaczyna pasować za każdym razem po ostatnim znaku, który pasował do poprzedniej okazji.
Użycie lookbehind i lookahead rozwiązuje ten problem i sprawia, że wyrażenie regularne jest również nieco krótsze:
:%s/\n\@<!\n\n\@!/\r\r/g
\n\@<!\n
oznacza to , że jakikolwiek podział linii, który nie jest zaraz po kolejnym, jest poprawny? Ale nie mogłem zrozumieć, co \n\@!
to znaczy. Chciałbym to zrozumieć, abym mógł się nauczyć i zastosować go do innych wzorców wyszukiwania :)
\n\@<!\n
oznacza każdy podział linii, który nie następuje natychmiast po kolejnym podziale linii. \n\@!
dopasowuje z zerową szerokością, jeśli poprzedni atom (tj. \n
) nie pasuje tuż przed tym, co następuje. Spróbuj :help \@<!
zobaczyć dokumentację na ten temat w vimie. I
Inny sposób:
%s/\(.\)\n\(.\)/\1\r\r\2/
Co znaczy,
\(.\) match and capture a non-newline character,
\n match a newline
\(.\) match and capture a non-newline character
zamień na: pierwsze przechwytywanie, podwójne znaki nowego wiersza i drugie przechwytywanie.
Na przykład line1\nLine2
wyniki w \1 = 1
i \2 = L
.
Popraw mnie, jeśli się mylę. Myślę, że używasz litery k, gdy jesteś w trybie poleceń, aby przejść w dół linii. Następnie wejdź w tryb wstawiania i dodaj następny wiersz. Powtórzyć w razie potrzeby? Mam nadzieję że to pomoże!
k
przesuwa się w górę linii. j
przesuwa się w dół linii.
/[^\n]\n[^\n]
:map <F2> no<esc><F2>
Następnie naciśnij <F2>
. Spowoduje to wyszukanie dwóch kolejnych niepustych linii, a następnie wielokrotne dodawanie linii między nimi.
Edytować:
Oto alternatywny sposób, aby to zrobić za pomocą jednego globalnego wyszukiwania i zamiany:
:%s/\([^\n]\)\n\([^\n]\)/\1\r\r\2/g
Wypróbuj to polecenie ( 16
znaki):
:%!sed G|cat -s
:%norm o
ale okazuje się, że to nie działa zgodnie z przeznaczeniemo
. +1