Ścieżka środowiska zastępczego VIM, aby uzyskać ścieżkę dołączania

0

Chcę zbudować includeścieżkę ze zmiennej środowiskowej vim. Chcę zachować tylko te wystąpienia, które kończą się jak /share/binw tej zmiennej, i zmień je na include. Chcę to zrobić na .vimrc, dlatego użyłem tej vim substitute()funkcji.

Jako test użyję tej zmiennej:

export TEST=/afs/test/share/bin:/afs/test2/share/bin:/afs/test/bin:/afs/test3/share/bin:/cvmfs/x86_64-slc6-gcc47-opt/share:/cvmfs/x86_64-slc6-gcc47-opt/bin

Pożądanym wynikiem dla tego przykładu jest:

TEST=/afs/test/include /afs/test2/include /afs/test3/include

Próbując osiągnąć ten wynik, utknąłem z następującymi dwoma pytaniami:


Pytanie 1

Ponieważ miałem problem z użyciem substitute()metody vim (wyjaśnionej poniżej), otworzyłem plik, powiedzmy lala, z tym samym tekstem ze $TESTzmiennej środowiskowej:

/afs/test/share/bin:/afs/test2/share/bin:/afs/test/bin:/afs/test3/share/bin:/cvmfs/x86_64-slc6-gcc47-opt/share:/cvmfs/x86_64-slc6-gcc47-opt/bin

I użył polecenia, s/share\/bin:/include /gaby uzyskać:

/afs/test/include /afs/test2/include /afs/test/bin:/afs/test3/include /cvmfs/x86_64-slc6-gcc47-opt/share:/cvmfs/x86_64-slc6-gcc47-opt/bin

potem użyłem polecenia %s#\(/.*include\)\(.*\)#\1#g, w wyniku czego:

/afs/test/include /afs/test2/include /afs/test/bin:/afs/test3/include

Ale kiedy to zrobię na vimie

:echo substitute(substitute($TEST,"share/bin:","include ","g"),"\(/.*include\)\(.*\)","\1","g")

Dostaję:

/afs/test/include /afs/test2/include /afs/test/bin:/afs/test3/include /cvmfs/x86_64-slc6-gcc47-opt/share:/cvmfs/x86_64-slc6-gcc47-opt/bin

więc moje pierwsze pytanie brzmi:

Dlaczego nie substitute()daje tego samego rezultatu podczas używania substitute?


Pytanie 2

Na koniec chcę usunąć wszystkie wystąpienia podobne do /afs/test/bin::

/afs/test/include /afs/test2/include /afs/test/bin:/afs/test3/include

, to znaczy, że nie ma na nim uwzględnienia. Próbowałem:

%s#\(/.\{-}include\)\@<=\(/| \)\{-}.\{-}:# #

Ale pasuje /afs/test2/include /afs/test/bin:i daje w wyniku:

/afs/test/include /afs/test3/include

Jak mogę usunąć te wystąpienia tekstowe, które nie miały / share / bin?

Werner
źródło
1
Jednym z problemów, które masz (może to nie być jedyny problem), jest używanie odwrotnych ukośników w podwójnych cudzysłowach (np. "\(/.*include\)Które nie działają tak, jak się wydajesz. To będzie dosłowne (znak, a nie \(funkcja wyszukiwania) Albo użyj pojedynczych cudzysłowów, albo użyj znaku odwrotnego ukośnika, aby zachować go w ciągu. Nie zamierzam próbować odszyfrować reszty, ponieważ funkcje listy w bieżącej odpowiedzi są o wiele ładniejsze. :-)
Ben

Odpowiedzi:

2

Twój kod nie jest łatwy do naśladowania i ogólnie substitute()powinien się zachowywać :s, więc nie mogę powiedzieć dokładnego problemu. Jednak całe twoje podejście zależy wyłącznie od zamiany tekstu, co czyni go tak złożonym. Od wersji 7 Vim ma (zainspirowane Pythonem) funkcje do pracy z listami i właśnie tego chciałbym użyć tutaj. Pokażę ci to krok po kroku:

" Setup
let $TEST='/afs/test/share/bin:/afs/test2/share/bin:/afs/test/bin:/afs/test3/share/bin:/cvmfs/x86_64-slc6-gcc47-opt/share:/cvmfs/x86_64-slc6-gcc47-opt/bin'

" Turn into List.
let dirs = split($TEST, ':')

" Remove unwanted dirs, then substitute the rest.
call filter(dirs, 'v:val =~# "/share/bin$"')
call map(dirs, 'substitute(v:val, "/share/bin$", "/include", "")')

" Combine back into String.
let result = join(dirs, ' ')
echo result

Wydajność:

/afs/test/include /afs/test2/include /afs/test3/include
Ingo Karkat
źródło
1
Potrzebowałem jeszcze jednej minuty, aby sformatować i zweryfikować moją odpowiedź ;-)
romainl