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ć
:g/^Level \d:/{COMMANDS}
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
:let i = 1 | g/^Level \d:/s/^/\=printf("%02d ", i)/ | let i = i+1
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 spacje 2
i pad z 0 0
. 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 nam 01
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
:let i = 1 | g/^Level \d:/execute "normal! I" . printf("%02d ", i) | let i = i+1
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 jest I
, które wstawia na początku linii. Gdybyśmy go użyli dd
, 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łowa 2w
, szarpanie do i-tego znaku „h” y" . i . "th
, przejście do końca wiersza $
i wklejanie p
.
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ć.
:unlet! i
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.
:let j = 0
:let i = []
:while j < 11 | let i += [1] | let j += 1 | endwhile
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 poziomusubstitute(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:
:unlet! i | unlet! j | let j = 0 | let i = [] | while j < 11 | let i += [1] | let j += 1 | endwhile
:g/^Level \d:/let ind=str2nr(substitute(getline("."), "^Level \\(\\d\\):.*", "\\=submatch(1)", "")) | s/^/\=printf("%02d ", i[ind])/ | let i[ind] += 1
Za pomocą normalnego polecenia:
:unlet! i | unlet! j | let j = 0 | let i = [] | while j < 11 | let i += [1] | let j += 1 | endwhile
:g/^Level \d:/let ind=str2nr(substitute(getline("."), "^Level \\(\\d\\):.*", "\\=submatch(1)", "")) | execute "normal! I" . printf("%02d ", i[ind]) | let i[ind] += 1
Przykładowe dane wejściowe:
Level 1: stuff
Level 1: Stuff
Some text
Level 3: Other
Level 1: Meh
Level 2: More
Przykładowe dane wyjściowe:
01 Level 1: stuff
02 Level 1: Stuff
Some text
01 Level 3: Other
03 Level 1: Meh
01 Level 2: More