Mam taki plik tekstowy (używam gVim w systemie Windows)
foo bar baz quux corge grault garply waldo fred plugh [...150 more lines...] xyzzy thud
Chcę dodać liczbę do każdego wiersza w pliku. Nie używamy :set number
, ale dodajemy liczbę jako tekst poprzedzający każdy wiersz w następujący sposób, aby numer był częścią pliku.
1. foo bar baz quux 2. corge grault garply 3. waldo fred plugh [...~150 more lines...] 155. xyzzy thud
Komentarze
Odpowiedź
W czystym stylu Vima:
:%s/^/\=line(".").". "
Wyjaśnienie:
:%s/^/ " the substitution will be applied to the beginning of every line \= " the rest of the replacement part is an expression line(".").". " " the expression returns the current line number concatenated with a dot and a space
Zobacz :help \=
i :help line()
.
Używanie wyrażenia w części zamiennej jest bardzo potężne, a FWIW jest całkiem dobrym punktem wejścia do vimscript.
Komentarze
- Jak mogę dodać to bardzo przydatne polecenie do mapy klawiszy w vimrc?
- Aby dostać się do tematu pomocy vim na temat podstawiania:
:help sub-replace-expression
Odpowiedź
Jedną z fajnych rzeczy w makrach Vima jest to, że mogą się powtarzać (mogą się wywoływać ):
- Wyczyść rejestr q:
qqq
- Dodaj numer do pierwszej linii:
ggI1.
(nie zapomnij o spacji!) - Wróć na początek wiersza i zacznij nagrywać makro:
0qq
- Skopiuj numer:
- Przesuń wiersz w dół i wklej numer:
+P
- Przejdź z powrotem na początek wiersza i zwiększ liczbę:
0<c-a>
- Wróć na początek wiersza (aby makro nie pękało, gdy osiąga podwójne cyfry!):
0
- Wywołaj makro raz, aby było rekurencyjne. W tym momencie w rejestrze q nadal nic nie ma, więc nic się nie stanie:
@q
. - Zapisz makro:
q
- Wywołaj makro jeszcze raz i zobacz, jak lecą iskry !:
@@
Makro będzie następnie kontynuuj wywoływanie samego siebie, aż dotrze do końca pliku.
Możesz użyć rekurencyjnej sztuczki makr do wielu innych podobnych problemów, więc dobrze jest być świadomym.
Jeśli z jakiegoś powodu nie chcesz używać makra rekurencyjnego, możesz pominąć kroki 1 i 8 i użyć licznika , aby uruchomić makro wiele razy, np. 100@q
uruchomi makro q
100 razy.
Komentarze
- Potężne rzeczy, kłaniam się twojemu mistrzostwu. Makra są dla mnie jak czarna magia …
- @ropata, makro to tylko sekwencja (głównie) poleceń trybu normalnego.
- @romainl Myślę, że to lepiej myśleć o tym jako o sekwencji naciśnięć klawiszy .
- @Rich, może to być sekwencja wielu rzeczy, w tym poleceń ex.
- @romainl Tak, to ' dlatego uważam, że ' najlepiej jest myśleć o tym jako o naciśnięciu klawisza. Odtwarza dokładnie to, co wpisujesz na klawiaturze (w tym, jak mówisz, polecenia ex), tak jakbyś wpisał to wszystko ręcznie.
Odpowiedz
Lubię używać globalnego polecenia vim do wykonywania takich zadań. Dotyczy to dodawania iteracji na początku wiersza lub modyfikacji symbolu w tekście. Wygląda na bardziej skomplikowane niż inne rozwiązania, ale jest dość elastycznym wzorcem do użycia, gdy masz go pod ręką i można go łatwo zmodyfikować bez większego zastanowienia.
Najpierw wybierz zakres (który chcesz to zastosować). Zwykle używam znaków (np.ma
w pierwszym wierszu i mb
w drugim, ale możesz też użyć numerów wierszy lub selekcji wizualnej), a następnie wprowadź modyfikację następujące polecenie (obecnie dostosowane do Twojego przypadku użycia)
:let i=1|"a,"bg/^/s/^/\=i.". "/|let i=i+1
Dekonstrukcja
:let i=1
Spowoduje to ustawienie zmiennej i
z wartością początkową. Zwykle listy zaczynają się od 1, więc ustawiam i na 1.
|
Pasek rozpoczyna nowe polecenie
"a,"b
Ustawia zakres następnego polecenia. Przechodzę od znaku a
do oznaczenia b
, które zostanie ustawione w pierwszym i ostatnim wierszu listy.
g/^/
To jest polecenie globalne. Przeszukuje plik (lub zakres) pod kątem danego wyrażenia regularnego i wykonuje resztę wiersza poleceń w każdej linii, która została dopasowana. Dopasowuję każdy wiersz, wyszukując „początek wiersza”. Jeśli masz tekst taki jak
Item some txt other text Item second item whatever Item third
i chcesz umieścić te etykiety tylko przed Item
i zignoruj pozostałe wiersze, zamiast tego wykonaj g/Item/
lub g/^Item/
(przyjmując literalny tekst pozycji )
s/^/\=i.". "/
Powoduje to wykonanie wyrażenia regularnego w celu zastąpienia początku wiersza wartością i
połączoną z a .
. Generalnie możesz to zrobić na wszystko (na przykład zastąp etykietę Item
numerem).
|let i=i+1
Mimo że pasek uruchamia nowe polecenie, ustawia drugie polecenie, które ma być uruchamiane w ramach polecenia globalnego, zamiast po jego zakończeniu. W rezultacie zwiększamy i
zanim następna linia zostanie przetworzona przez g. Oto kolejne miejsce elastyczności. Modyfikacja i może być dowolna (zwiększ o 2, wywołaj funkcję, która generuje następny element ciągu Fibonacciego, cokolwiek).
Odpowiedź
Dodaj liczby do wszystkie linie
Można użyć :%!nl -ba
lub :%!cat -n
, które dodadzą numery linii do wszystkich linii.
W systemie Windows „ve mieć zainstalowany Cygwin / MSYS / SUA.
Dodaj numery do wybranych linii
Aby dodać numery tylko dla wybranych linii, wybierz je w tryb wizualny ( v i kursory), a po zakończeniu – wykonaj polecenie: :%!nl
(ignoruj puste linie) lub :%!cat -n
(łącznie z pustymi wierszami).
Formatowanie
Aby usunąć dodatkowe spacje, zaznacz je w bloku wizualnym ( Ctrl + v ) i usuń je ( x ).
Aby dodać kilka znaków (.
, :
, ) po liczbach, zaznacz je w bloku wizualnym ( Ctrl + v ), a następnie dołącz znak ( A , wpisz znak, a następnie zakończ Esc ).
Komentarze
- To nie daje takiego samego formatowania jak podane w pytaniu. Jednak podoba mi się prostota rozwiązania.
- @KarlYngveLerv å g Dziękuję, zawarłem to w odpowiedzi.
Odpowiedź
Modyfikacja odpowiedzi romainl :
:%s/^\(\d\+\. \)\?/\=line(".").". "
To nie tylko doda numery linii, ale także zastąpi numery linii wyjściowych, jeśli już tam są. Of, jeśli wstawiłeś wiersz w połowie drogi, numeracja wszystkiego zostanie zmieniona zgodnie z oczekiwaniami.
Działa to poprzez zastąpienie dowolnej liczby, po której następuje a. I spacja na początku wiersza, nową liczbą . To oczywiście się zepsuje, jeśli masz linię, która już zaczyna się od tego wzorca, więc używaj jej z przemyśleniem.
Dodana część:
-
^
– początek linii -
\(
– Rozpocznij nową podgrupę -
\d\+
– Dopasuj cyfrę raz lub więcej razy -
\.
– Dopasuj kropkę (
.
) i spacją.
-
\)
– Zakończ podgrupę -
\?
– Ustaw grupę jako opcjonalną, aby działała jak poprzednio, jeśli nie ma jeszcze numeru w tej linii.
Dodatkowa wskazówka :
Aby usunąć numery wierszy, możesz użyć tego samego wzorca z pustą częścią repalce:
:%s/^\(\d\+\. \)\?//
Odpowiedź
I1. <esc>^qqyWjP^<C-a>q
To numeruje pierwsze dwie linie i możesz nacisnąć @q
aby ponumerować kolejne linie (lub wpisz np. 18@q
, jeśli chcesz liczyć łącznie 20 wierszy).
Wyjaśnienie:
I1. <esc> Number the first line hqq Go back to the start of the line and start recording a macro yWjP Copy the line number to the next line ^<C-a> Increment the next line"s line number q Finish recording
Zaletą tego jest to, że nie wymaga żadnych zewnętrznych poleceń, co jest przydatne, jeśli na przykład praca z Vimem w systemie Windows.
Komentarze
- Po wpisaniu
1. <esc>h
jesteś na druga kolumna, a nie pierwsza kolumna. Zamieniłbymh
na0
, po czym myślę, że twoje rozwiązanie powinno być bardzo dobre. - @KarlYngveLerv å g Ups, to była literówka. Dzięki, naprawiłem to.
- Żaden problem. Jednak nadal nie zaktualizowałeś wyjaśnienia. Ponadto: na wielu klawiaturach
^
czeka na drugi znak, aby umożliwić wpisywanie kombinacji, takich jak^a -> â
. Wciąż zgadzam się, że to najlepsze rozwiązanie, ale myślę, że należy również wspomnieć o tym.
Odpowiedź
I myślę, że wybrana odpowiedź jest najlepsza, ale w duchu różnorodności zaproponuję alternatywę za pomocą zewnętrznego programu:
:%!cat -n
To przefiltruje cały bufor (zgodnie z oznaczeniem %
) za pośrednictwem programu zewnętrznego, cat
, gdzie -n
flaga poprzedza każdy wiersz wejścia numerem wiersza.
Oczywiście wymaga to zainstalowania cat
, co jest prawdą dla (prawdopodobnie) wszystkich systemów Unix -podobnych systemów.
Sprawdź :help :range!
, aby uzyskać więcej informacji na temat filtrowania przez programy zewnętrzne.
Komentarze
- Zdaję sobie sprawę, że pytający używa gVim w systemie Windows, więc to rozwiązanie prawdopodobnie ' nie zadziała. Jednak myślę, że nadal zapewnia pewne możliwości innym t ucz się z tego.
- Jeśli ' zainstalowałeś
msysgit
i dodałeś to do swojej PATH (IIRC it ' jest opcją instalacji), to rozwiązanie powinno również działać w systemie Windows. -
cat -n
nie jest POSIX, alenl
tak, więc może to być lepsza opcja.
Odpowiedź
Trochę hakerskie rozwiązanie może być następujące (wszystko zapisane między i> należy wstawić po naciśnięciu Ctrl + v ):
:%normal :redir @"<Enter>:-=<Enter>:redir END<Enter>I<C-R>".<Tab><Esc>kdd
Dekonstrukcja
:%normal {commands}
uruchamia polecenie trybu normalnego w każdej linii określonej przez zakres, w tym przypadku w każdej linii
:redir @"
przekierowuje każde wyjście wykonane przez polecenia ex do nienazwanego bufora.
:.=
jest poleceniem ex, które wyświetla bieżącą linię numer (niestety z poprzedzającym znakiem nowej linii)
:redir END
przestaje przekierowywać do nienazwanego bufora
I<C-R>".<Tab><Esc>
wstawia zawartość nienazwanego buforu z rozszerzeniem. i tabulator na początku każdego wiersza i wychodzi z trybu wstawiania.
kdd
przechodzi o jedną linię w górę i usuwa znak nowej linii, który jest wynikiem:. = polecenie.
awk
jest prawdopodobnie narzędziem do tego zadania. Ale ja ' mw systemie Windows (westchnienie).cat
lubnl
, które mogą wykonywać wiersze liczbowe, ale nie mają ' t ogólnie dostępne w systemie Windows (jak wskazuje OP na podstawie ich komentarza na tematawk
). Dwa najlepsze rozwiązania to czysty Vim. Wreszcie, wszystkie linie kontra jeden para to tylko kwestia wyboru zakresu. Z pewnością nie jest to duży problem.