Mam problem. Mogę wymyślić dwa ogólne podejścia do rozwiązania, ale nie znam szczegółów dla żadnego z nich.
...
Level 1: cũng also
Level 1: và and
Level 1: như like; such as
Level 2: các plural marker
Level 2: của belonging to
...
Do każdej linii rozpoczynającej się od „Poziomu n” chcę wstawić liczbę rozpoczynającą się od „01”. Dla uproszczenia wstawmy liczbę.
Podejście 1: Ręcznie wybierz wszystkie linie o tym samym poziomie. Wywołaj magię, której wkrótce się nauczę.
Podejście 2: Napisz wyszukiwanie i zamień, które pasują do wszystkich wierszy o danym poziomie, który przy każdym dopasowaniu zawiera liczbę w tekście zamiany, która zwiększa się o jeden z każdym dopasowaniem.
Znalazłem podobne pytania na StackOverflow lub na innych stronach Vima, ale wydaje się, że każdy z nich ma jeden lub więcej z następujących problemów:
- Chodzi o wstawienie bieżącego numeru linii, a nie o dowolnym, ale rosnącym numerze.
- Nie wprowadza zerowej liczby.
- W rzeczywistości nie działa w przypadku wyborów w moim Vimie 7.4 działającym w systemie Windows 7. (Te powodują błąd
E481: No range allowed
).
Korzystam z gVim w systemie Windows z mswin.vim, ale najlepsze może być rozwiązanie, które działa na wszystkich instalacjach waniliowych Vim bez konieczności dostosowywania instalacji.
Odpowiedzi:
Podobnie do odpowiedzi na https://vi.stackexchange.com/a/818/227 , możesz użyć polecenia globalnego.
Za jego pomocą możesz poinstruować vima, aby szukał linii pasujących do wzorca, a następnie wykonywał na nim polecenia.
W twoim przypadku chcesz wstawić tekst do linii zaczynających się od „Poziomu N:”, aby nasze globalne polecenie mogło być
Użycie polecenia zastępczego (zastąpienie wyrażenia regularnego) dla polecenia
Polecenia są zabawniejsze. Zwykle lubię zastępować wyrażenia regularne takimi rzeczami, ponieważ zmienne są łatwe w użyciu.
Przykład twojego pytania
Jak to działa
W sekcji zastępowania polecenia podstawienia może znajdować się wyrażenie.
Pierwszą rzeczą, jaką zrobimy, jest ustawienie zmiennej
i
jako liczby początkowej. Wybrałem 1, ale wystarczy dowolna liczba.let i = 1
Następnie uruchamiamy nasze globalne polecenie, które ustawia nas do działania na dopasowanych liniach.
g/^Level \d:/
Nasze globalne polecenie wstawi wartość i zwiększy licznik za pomocą polecenia podstawienia i polecenia let.
s/^/\=printf("%02d ", i)/ | let i = i+1
Wyrażenie regularne polecenia podstawienia znajduje początek wiersza
^
i zastępuje go wyrażeniem, a nasze wyrażenie będzie wynikiem sformatowanego wydruku. Podobnie jak w języku C, printf vima przyjmuje parametry formatowania.%02d
oznacza konwersję argumentu tak, jakby był liczbą dziesiętnąd
, zajmując co najmniej 2 spacje2
i pad z 00
. Aby uzyskać szczegółowe informacje i inne opcje konwersji (w tym formatowanie zmiennoprzecinkowe), zobacz:help printf
. Dajemy printf naszą zmienną zliczającąi
i daje nam01
to pierwszy raz,02
drugi raz itp. Przydaje się to komendzie podstawienia, aby zastąpić początek linii, skutecznie wstawiając wynik printf na początku.Zauważ, że mogę umieścić spację po d:
"%02d "
. Nie pytałeś o to w pytaniu (i nie widziałem przykładowego wyniku), ale podejrzewałem, że chcesz oddzielić liczbę od słowa „Poziom”. Usuń spację z ciągu podanego printf, aby wstawić liczbę tuż obok L na poziomie.Na koniec
let i = i + 1
zwiększa to nasz licznik po każdej zmianie.Można to ogólnie zastosować do zastąpienia części linii, które są zgodne innymi kryteriami, dowolnymi danymi funkcjonalnymi.
Używanie połączonych normalnych poleceń
Jest to dobre w przypadku prostych wstawek lub złożonej edycji. Podobnie jak w przypadku podstawiania, użyjemy globalnego, aby dopasować, ale zamiast podstawienia wyrażeń regularnych wykonamy serię operacji, jakby zostały wpisane przez użytkownika.
Przykład twojego pytania
Jak to działa
Użyte wartości są bardzo podobne do zamiennika (nadal używamy printf do sformatowania naszego numeru, aby był uzupełniony o 2 cyfry), ale operacja jest inna.
Tutaj używamy polecenia execute, które pobiera ciąg i uruchamia go jako polecenie ex (
:help :exe
). Konstruujemy ciąg, który łączy „normalne! Ja” z naszymi danymi, które będą „normalne! I01” za pierwszym razem i „normalne! I02” za drugim razem itp.Te
normal
operacje Wykonuje polecenie jak w trybie normalnym. W tym przykładzie naszym normalnym poleceniem jestI
, które wstawia na początku linii. Gdybyśmy go użylidd
, usunąłby linię,o
otworzyłby nową linię po dopasowanej linii. To tak, jakbyś wpisałI
(lub jakąkolwiek inną operację) w trybie normalnym. używamy!
po,normal
aby upewnić się, że żadne mapowania nie staną na naszej drodze. Zobaczyć:help :normal
.To, co jest wstawiane, to wartość naszego printf, jak w pierwszym przykładzie użycia substytutu.
Ta metoda może być bardziej wyrafinowana niż regex, ponieważ możesz robić takie rzeczy, jak
execute "normal! ^2wy" . i . "th$p"
przejście do początku tekstu^
, przesuwanie do przodu o 2 słowa2w
, szarpanie do i-tego znaku „h”y" . i . "th
, przejście do końca wiersza$
i wklejaniep
.To prawie jak uruchamianie makra, ale tak naprawdę nie zużywa rejestru i może łączyć ciągi z dowolnych wyrażeń. Uważam to za bardzo potężne.
Podejdź, gdzie każdy poziom ma swój własny licznik
Możesz chcieć, aby każdy poziom miał swój własny licznik. Jeśli znasz maksymalną liczbę poziomów z wyprzedzeniem, możesz wykonać następujące czynności (dodanie dodatkowego kodu w celu znalezienia największego poziomu może nie być zbyt trudne, ale spowodowałoby, że ta odpowiedź byłaby zbyt długa. Jest coraz dłuższa).
Po pierwsze, wypuśćmy ja, na wypadek, gdybyśmy użyli go już jako liczby całkowitej. Nie możemy przekonwertować i na listę, musimy ją w ten sposób utworzyć.
Następnie ustawmy i jako listę zawierającą liczbę poziomów. W swoim pytaniu pokazałeś 2, ale załóżmy 10 dla zabawy. Ponieważ indeksowanie list jest oparte na 0, a nie chcę zawracać sobie głowy poprawianiem opartego na 1, tak jak twoja lista, utworzymy po prostu wystarczającą liczbę elementów (11) i nigdy nie używamy indeksu 0.
Następnie potrzebujemy sposobu na uzyskanie numeru poziomu. Na szczęście substytut jest również dostępny jako funkcja, więc podamy mu naszą linię i wyodrębnimy numer poziomu
substitute(getline("."), "^Level \\(\\d\\):.*", "\\=submatch(1)", "")
Ponieważ i jest teraz listą 11
1
s (każdy indeks jest licznikiem naszego poziomu), możemy teraz dostosować jeden z powyższych przykładów, aby wykorzystać wynik tego podstawienia:Za pomocą polecenia zastępczego:
Za pomocą normalnego polecenia:
Przykładowe dane wejściowe:
Przykładowe dane wyjściowe:
źródło
Możesz budować z https://stackoverflow.com/a/4224454/15934, aby zerować swoje liczby.
Ale aby uprościć akcję uzupełniania liczb, wybrałbym parę funkcji i polecenia:
Następnie wybierz swoje linie i wpisz
:PrependNumber
(zobaczysz:'<,'>PrependNumber
. [Uwaga: Polecenie przyjmuje opcjonalny parametr: wzór, przed którym liczba zostanie wstawiona]źródło
line(".")
znaczy „użyj bieżącego numeru linii”? To był mój problem 1. z poprzednimi odpowiedziami, które mogłem znaleźć.$HOME/vimfiles/plugin/whatevernameyouwish.vim
. Lub nawet$HOME/_vimrc
(nazwa pliku systemu Windows), jeśli wolisz (po raz pierwszy). Jeśli nie masz pewności, co $ HOME znajduje się na twoim komputerze, zapytaj vima, co on myśli ->:echo $HOME
:source
jeśli skrypt vim jest poprawnie zainstalowany we właściwym katalogu ({rtp} / plugin lub {rtp} / ftplugin / {filetype} / ftplugin dla wtyczek specyficznych dla rodzaju pliku).:source
z tym musieliśmy grać ponad półtorej dekady temu.Możesz do niego podejść, rejestrując makro. Zaczynając od oryginalnego pliku, dodaj pierwszą instancję z numerem.
Przesuń kursor do
01
, wybierz i pociągnij goyiw
. Teraz chcesz zarejestrować swoje działania od tego momentu.qq/^Level 1<CR>P<C-A>A<space><esc>0yiwq
qq
Uruchom makro w rejestrze q/^Level 1<CR>
Wyszukaj wiersz rozpoczynający się od „Poziomu 1”P
wklej przed kursorem (zawiera twój numer)<C-A>
zwiększa liczbęA<space><esc>
Wstaw spację po numerze0
Przejdź na początekyiw
wybierz bieżący numerq
Zakończ makroNastępnie powtórz to makro za pomocą
@q
.źródło
<C-A>
kontrola + a? To zaznacza wszystko w Vimie na Windowsie.