Jak skopiować każdą linię 11 razy, zwiększając ostatnią „1” w każdej linii od 2 do 12

9

Mam kilka linii w pliku i chciałbym skopiować każdą linię 11 razy (zamieniając każdą linię w 12 linii) i zwiększać ostatnią „1” w każdej linii, tak aby 12 linii miało „1” do „ 12 ”, gdzie początkowo była„ 1 ”. W każdej linii mogą występować inne wystąpienia „1”, ale „1”, które chcę zwiększyć, będzie zawsze ostatnim wystąpieniem w każdej linii. Innym sposobem spojrzenia na to jest to, że ostatnie „1” jest zawsze po „/ nt /” - jak w „/ nt / 1” (i zawsze będzie to jedyne wystąpienie „/ nt / 1” w każdej linii) .

Na przykład, jeśli mam:

1stlineblahblahblah/nt/1blah
2ndlineblahblahblah/nt/1blah
3rdlineblahblahblah/nt/1blah

Chcę to przekształcić w:

1stlineblahblahblah/nt/1blah
1stlineblahblahblah/nt/2blah
1stlineblahblahblah/nt/3blah
1stlineblahblahblah/nt/4blah
1stlineblahblahblah/nt/5blah
1stlineblahblahblah/nt/6blah
1stlineblahblahblah/nt/7blah
1stlineblahblahblah/nt/8blah
1stlineblahblahblah/nt/9blah
1stlineblahblahblah/nt/10blah
1stlineblahblahblah/nt/11blah
1stlineblahblahblah/nt/12blah
2ndlineblahblahblah/nt/1blah
2ndlineblahblahblah/nt/2blah
2ndlineblahblahblah/nt/3blah
...

Wcześniej znalazłem polecenie:

:for i in range(0,12) | put ='1stlineblahblahblah/nt/'.i.'blah' | endfor

działa w tym celu, ale musiałbym ręcznie uruchomić to polecenie dla każdej linii i sam wpisać każdą linię (lub skopiować i wkleić). Czy istnieje sposób na pobranie linii, które są już w pliku, i po prostu uruchom jedno polecenie, które zamienia każdą linię na dwanaście, w sposób, który opisałem?

Z góry dziękuję wszystkim, którzy mogą mi w tym pomóc. Chciałem też zauważyć, że jest to moje drugie pytanie tutaj i cieszyłem się, że otrzymałem kilka szybkich i skutecznych rozwiązań dla mojego pierwszego pytania, za które byłem najbardziej wdzięczny.

blewasiereisawelba
źródło

Odpowiedzi:

8

Oto podstawienie, które rozwiązuje problem:

:%s/\(.*\)1\(.*\)/\=join(map(range(1, 12), 'submatch(1) . v:val . submatch(2)'), "\n")

Podstawienie pasuje do każdego wiersza zawierającego „1” i przechwytuje tekst przed {c1}i po {c2}ostatnim „1”. Dla każdej dopasowanej linii zakres liczb od jednego do dwunastu {n}jest odwzorowywany w celu utworzenia dwunastu linii formularza {c1}{n}{c2}. Każda grupa dwunastu linii zastępuje skojarzoną, oryginalnie dopasowaną linię.

Zobaczyć :h sub-replace-expression.

djjcast
źródło
2
Wow, świetne polecenie w jednym wierszu. Pamiętam, że znalazłeś także eleganckie jedno-liniowe rozwiązanie dla pierwszego pytania, które zadałem kilka tygodni temu. Bardzo dobra robota. Dziękuję Ci bardzo. Zgaduję również, że istnieje sposób, aby umieścić to w pliku _vimrc, aby móc wykonać łatwe do zapamiętania polecenie lub funkcję bez wpisywania całej linii powyżej (lub konieczności przewijania listy poprzednich poleceń), ale Nie znam jeszcze składni _vimrc, aby wiedzieć, jak to zrobić.
ablewasiereisawelba
10

Możesz to zrobić przez

  1. nagrywanie makra, a następnie
  2. za pomocą globalpolecenia ex wykonać makro n liczbę razy dla każdej linii w pliku.

Po zarejestrowaniu makra cofnij zmiany dokonane podczas nagrywania, w przeciwnym razie pojawi się n + 1 dodatkowych linii dla pierwszej linii oraz n dla kolejnych linii.

Zapisz makro do arejestru za pomocą

qayyp$?\d<CR><C-A>q

Zapisuje do register a( qa...q) następujące polecenie:

  • yyp: zduplikuj bieżącą linię
  • $: przejście do końca linii
  • ?\d<CR>: wyszukaj wstecz pojedynczą cyfrę
  • <C-A>: przyrost cyfry pod kursorem o jeden

Po zarejestrowaniu makra usuń zmiany dokonane podczas jego rejestrowania poprzez cofnięcie ( uu) lub usunięcie bieżącej linii ( dd). Następnie powtórz makro 11(lub dowolną liczbę) razy dla każdej linii w pliku za pomocą polecenia global:

:g//normal 11@a
jjaderberg
źródło
2
Zadziałało! Bardzo ładnie, dziękuje. Początkowo miałem problem z Ctrl-a podświetleniem wszystkiego zamiast dodawania, ponieważ używam gVima w Windowsie ... ale zrobiłem szybkie wyszukiwanie i znalazłem ten wątek - stackoverflow.com/questions/289681/... - gdzie ja skorzystałem z sugestii umieszczenia nnoremap <kPlus> <Ca> nnoremap <kMinus> <Cx> w _vimrc, abym mógł używać klawiszy „+” i „-” do dodawania i odejmowania. Ponadto globalne polecenie musiało być dla mnie: g // normal 11 @ a, ale łatwo to rozgryźć. Dziękuję Ci!
ablewasiereisawelba
6

Dwie drogi:

Użyj makra!

Począwszy od

1stlineblahblahblah/nt/1blah
2ndlineblahblahblah/nt/1blah
3rdlineblahblahblah/nt/1blah

Z kursorem w pierwszym wierszu

qqyyp$?\d<CR><Ctrl-a>q
10@q

Co robi:

qq Rozpocznij rejestrowanie makra w rejestrze q

yyp szarpnij bieżącą linię i wklej poniżej

$?\d<CR> Przejdź do końca linii i znajdź pierwszą cyfrę, patrząc wstecz

<Ctrl-a> Zwiększ liczbę

q Zatrzymaj rejestrowanie makra.

To pozostawia Ci:

1stlineblahblahblah/nt/1blah
1stlineblahblahblah/nt/2blah
2ndlineblahblahblah/nt/2blah
2ndlineblahblahblah/nt/3blah

Z kursorem w drugim wierszu. Po prostu powtórz to makro tyle razy, ile chcesz (na przykład powtórz je dziesięć razy za pomocą 10 @ q). Jeśli chcesz zautomatyzować ten proces dla każdej linii, wykonaj go globalnie dla każdej linii:

:g//normal 11@q

Alternatywnie, z nowszą wersją vima: Wklej wybraną linię jednak wiele razy, blok wizualny wybierz cyfrę, którą chcesz zwiększyć, i naciśnij g <Ctrl-a>. Powinno to zwiększać wszystkie liczby w bloku wizualnym, jak chcesz. Jest to jednak proces bardziej ręczny.

fruglemonkey
źródło
1
Wspaniale, nie wiedziałem o g <c-a>drodze. Dzięki za udostępnienie.
kba stoi z Moniką
1
@fruglemonkey Pierwsza część twojej odpowiedzi jest taka sama jak powyższa, ale mimo to dziękuję. Druga część, nie wydaje mi się, że działa dla mnie (chyba że robię coś złego), więc nie mogę używać właściwej wersji.
ablewasiereisawelba
5

Uważam, że najłatwiej jest używać makr do takich zadań. Po prostu zacznij rejestrować makro z q+ nazwą rejestru i wykonaj zadanie raz. Widzę tutaj jedno powtarzalne zadanie:

  • Wybierz linię
  • szarpać
  • wklej (spowoduje przejście do następnego wiersza)
  • idź do końca linii
  • cofnij się o jedno słowo
  • przyrost o jeden

Teraz zapisz wymagane naciśnięcia klawiszy, aby się zarejestrować a, w trybie normalnym:

qayyp$b<c-a>.

Usuń wiersz ponownie, aby sprawdzić, czy wykonanie makra 11 razy daje właściwy wynik dla jednej linii:

11@a

To robi! Cofnijmy więc ponownie i zautomatyzujmy cały proces w drugim makrze b:

qb11@aj

Teraz możesz wykonać @bdo końca pliku i powinien on wygenerować pożądany wynik. Brzmi skomplikowanie, ale tak naprawdę nie jest tak, gdy przyzwyczaisz się do typowych wzorców edycji.

kba stoi z Monicą
źródło
Nie jestem pewien, czy robię coś źle, ale wydaje się, że to nie działa. Postępowałem zgodnie z tym, co napisałeś, ale być może coś źle zrozumiałem lub nie wykonałem poprawnie. (Zwiększam pierwszą liczbę wiersza, a nie ostatnią liczbę wierszy.) Dziękujemy za odpowiedź.
ablewasiereisawelba
3
Myślę, że pierwsze makro powinno być qaVyp$b<c-a>. Lub lepiej, po prostu qayyp$b<c-a>.
Karl Yngve Lervåg
1
Dzięki, @ KarlYngveLervåg, masz rację, naprawiłem makro.
kba stoi z Monicą
2
Argh :( dzięki za dokładność @ablewasiereisawelba. Wydaje mi się, że makro qqyyp$?\d<CR><Ctrl-a>q@fruglemonkey i @jjaderberg jest lepsze, ponieważ wyszukuje ostatni numer. Zmienię go dla kompletności.
Kba stoi z Monicą
2
@kba Właśnie pomyślałem, że jeśli ktoś poświęci czas i wysiłek, aby odpowiedzieć na moje pytanie, mógłbym przynajmniej wypróbować jego rozwiązanie - nawet jeśli już znalazłem działające rozwiązanie od kogoś innego. Doceniam twój wysiłek - a jeśli to sprawi, że poczujesz się lepiej, wciąż jesteś o wiele mil przede mną. :)
couldwasiereisawelba
2

Zapisz następujące makro i użyj go dla każdej linii:

qqyy11p/\/\zs1<CR><C-v>10jg<C-a>q

Główną różnicą w porównaniu z innymi odpowiedziami jest to, że korzysta się z g<C-a>wyboru kolumny, który zwiększa każdą linię o inną liczbę. Sprawdź :help v_g_CTRL-Awięcej informacji. Użyłem również \zsdo wyboru pozycji początkowej wzoru, tak aby kursor zatrzymał się na liczbie po wyszukiwaniu.

Pamiętaj, że potrzebujesz najnowszej wersji Vima, aby to działało.

Vitor
źródło
1
@fruglemonkey również to zaproponował . Jest to fajna funkcja, choć dość nowa (według standardów vim), od 7.4.754, która nie została jeszcze dostarczona do wszystkich dystrybucji.
kba stoi z Moniką
Przepraszam, przepraszam
Vitor
1
@Vitor Mam właśnie gVima 7.4, więc nie sądzę, żebym mógł zrobić g<C-a>ten @fruglemonkey, o którym mówiłeś, ale dziękuję za odpowiedź. Powinienem zauważyć, że podczas próby makra - tuż przed przejściem do tej g<C-a>części, nie jest to ostatnia litera „1”, którą chcę zwiększyć, która jest podświetlana blokowo, ale zamiast tego jest to litera przed pierwszą „1” "znak, który zostanie podświetlony blokowo. (Także myślę, że będzie to miało być yy11pi 10jw makro, ponieważ Czekam na dodać 11 linii - w sumie 12.)
ablewasiereisawelba
1
Dziękuję za twój komentarz. Odpowiednio zaktualizowałem odpowiedź. Zdecydowałem się użyć \zs, ale równie dobrze mogłem po prostu dodać lpo <CR>.
Vitor,
1
Prawdopodobnie masz jakieś ustawienia w vimrc, które wpływają na wyszukiwanie wyrażeń regularnych. Spróbuj ponownie, zaczynając od Vima vim -u NONE. Właśnie to zrobiłem i działa to doskonale! W rzeczywistości nie ma możliwości, aby wyszukiwanie pasowało do pierwszego 1, ponieważ wymaga poprzedzającego go ukośnika.
Vitor,