Wyszukaj i zamień w vimie w określonych wierszach

99

mogę użyć

:5,12s/foo/bar/g

aby wyszukać fooi zamienić go barmiędzy wierszami 5 i 12. Jak mogę to zrobić tylko w wierszach 5 i 12 (a nie w wierszach pomiędzy)?

pfnuesel
źródło

Odpowiedzi:

78

Vim ma specjalne atomy wyrażeń regularnych, które pasują do pewnych linii, kolumn itp .; możesz ich użyć (ewentualnie oprócz zakresu), aby ograniczyć dopasowania:

:5,12s/\(\%5l\|\%12l\)foo/bar/g

Widzieć :help /\%l

Ingo Karkat
źródło
8
Bardziej skomplikowany sposób, niż się spodziewałem, ale doskonale odpowiada na moje pytanie. Dzięki!
pfnuesel
57

Możesz dokonać zamiany w linii 5 i powtórzyć ją przy minimalnym wysiłku w linii 12:

:5s/foo/bar
:12&

Jak zauważył Ingo, :&zapomina o twoich flagach. Ponieważ używasz /g, poprawnym poleceniem byłoby :&&:

:5s/foo/bar/g
:12&&

Zobacz :help :&i przyjaciele.

romainl
źródło
10
+1 za :&użycie tego, co niejasne . Jeśli są flagi ( s/../../g), to trzeba ich użyć :&&...
Ingo Karkat
10
@IngoKarkat, szczerze mówiąc, myślę, że \(\%5l\|\%12l\)jest bardziej niejasny niż:&
doubleDown
14

Zawsze możesz dodać cna końcu. Spowoduje to potwierdzenie każdego dopasowania.

:5,12s/foo/bar/gc
Dziekan
źródło
1
To może być koszmar, jeśli jest wiele meczów między liniami 5 i 12 (pamiętaj, że w grze jest gflaga)
doubleDown
1
@doubleDown To nie ma być uniwersalne rozwiązanie (gdzie jest wielu możliwych kandydatów), ale czy w większości przypadków naciśnięcie n5 lub 6 razy jest bardziej uciążliwe niż dodanie \(\%5l\|\%12l\)do instrukcji zastępczej?
Dziekan
Uważam, że to przydatne, chciałem zmienić każdą inną linię, byłoby to szybsze niż to, co ostatecznie zrobiłem.
tiktak
9

Interesujące pytanie. Wygląda na to, że istnieje tylko wybór zakresu, a nie wybór wielu wierszy:

http://vim.wikia.com/wiki/Ranges

Jeśli jednak masz coś specjalnego w liniach 5 i 12, możesz użyć :goperatora. Jeśli twój plik wygląda tak (numery tylko w celach informacyjnych):

 1     line one
 2     line one
 3     line one
 4     line one
 5     enil one
 6     line one
 7     line one
 8     line one
 9     line one
10     line one
11     line one
12     enil one

I chcesz zastąpić oneprzez enona liniach gdzie tam enilzamiast line:

:g/enil/s/one/eno/
eckes
źródło
5
to naprawdę dużo
doubleDown
1

Możesz użyć ed- liniowego edytora tekstu z podobnymi poleceniami do vi i vim. Prawdopodobnie poprzedza vi i vim.

W skrypcie (używającym dokumentu tutaj, który przetwarza dane wejściowe do znacznika EndCommand) wyglądałoby to następująco:

ed file <<EndCommands
    5
    s/foo/bar/g
    7
    s/foo/bar/g
    wq
EndCommands

Oczywiście poleceń ed można również używać w wierszu poleceń.

suspectus
źródło
3
Nie widzę przewagi nad vimalternatywą.
Bernhard
1
To samo można zrobić z Vimem; liczby można w rzeczywistości wstawić przed :s, ale nadal istnieje powielenie :spolecenia (czego unika rozwiązanie Romainla).
Ingo Karkat
Moim zdaniem użytkownik mógł chcieć wybrać znacznie więcej niż dwie linie do edycji. W takim przypadku mogłoby być interesujące podejście nieinteraktywne - czego AFAIK nie można zrobić z vimem.
suspectus
1
Och, Vim może to zrobić (np. W trybie „Ex”), ale masz rację, że powinno być lepsze inne narzędzie niż interaktywny edytor. Moje preferencje byłoby sed, chociaż ...
Ingo Karkat