Mam plik z kilkoma domyślnymi ustawieniami użytkownika. Chcę zmienić część tekstu, ale mam problemy wymyślanie dopasowywania i zamiany. Korzystając z następującego przykładu:
############################################################################### # Trackpad, mouse, keyboard, Bluetooth accessories, and input # ############################################################################### # Trackpad: enable tap to click for this user and for the login screen defaults write com.apple.driver.AppleBluetoothMultitouch.trackpad Clicking -bool true
Chcę zastąpić # Trackpad: ...
z running "Trackpad: ..."
Rozwiązując problem, wpadłem na coś, używając testera wyrażeń regularnych:
/\n\n#\s(.*)/g
Jeśli spróbuję użyć tego w Vimie, nie działa to dla mnie:
:/\n\n#\s(.*)/running "\1"/g
Myślę, że mój problem sprowadza się do dwóch konkretnych pytań:
- Jak uniknąć wyszukiwania
\n
znaków i zamiast tego upewnić się, że#
się nie pojawia na końcu grupy wyszukiwania? - Jak skutecznie korzystać z grup przechwytywania?
Poniżej znajduje się kilka świetnych odpowiedzi. Trudno wybrać pomiędzy wszystkimi trzema, jednak uważam, że wybrana odpowiedź jest najbardziej dokładna dla mojej oryginalnej specyfikacji. Zalecam wypróbowanie wszystkich trzech odpowiedzi z rzeczywistym plikiem , aby sprawdzić, co o nich myślisz.
Odpowiedź
Dla jasności… Wydaje mi się, że prosiłeś, aby to wynikało z podstawienia?
############################################################################### # Trackpad, mouse, keyboard, Bluetooth accessories, and input # ############################################################################### running "Trackpad: enable tap to click for this user and for the login screen" defaults write com.apple.driver.AppleBluetoothMultitouch.trackpad Clicking -bool true
W takim przypadku zalecam następującą komendę:
:%s/\n\n#\s\+\(.*\)/^M^Mrunning "\1"/
Wyjaśnienie wzorca
:s/PATTERN/REPLACEMENT/
jest poleceniem substytutem . Znak procentu :%s
sprawia, że działa on na całym pliku, a nie tylko na bieżącym wierszu.
\n\n
mówi, że interesująca nas linia musi występować po pustym wierszu. Jeśli poprzedni pusty wiersz nie był dla Ciebie ważny, wystarczyłoby ^
.
#\s\+
dopasowuje hash znak, po którym następuje jeden lub więcej białych znaków. \(.*\)
przechwytuje cały kolejny tekst w wierszu.
Objaśnienie tekstu zastępczego
^M^M
wstawia dwa końce wierszy, aby zastąpić \n\n
, które były obecne we wzorcu. W przeciwnym razie tekst zostałby przeniesiony na koniec wiersza poprzedzający pusty wiersz. Aby wpisać ^M
, naciśnij klawisze Ctrl-V Ctrl-M .
Następnie wstaw ciąg running
, a po nim wszystko, co zostało zapisane w nawiasach w podwójnych cudzysłowach.
Komentarze
Odpowiedź
Chciałbym użyć czegoś takiego:
:s/^#\s\+\(.\{-}\):/running "\1":/
-
^#
, aby dopasować#
znak zakotwiczony na początku wiersza (odpowiedź na pytanie 1) -
\s\+
, aby dopasować dowolną białą spację raz lub więcej razy -
\(
, aby rozpocząć grupę (to odpowiada na pytanie 2) -
.\{-}\
, aby dopasować dowolny znak 0 lub więcej razy w niechciwy sposób ; różni się to od.*
tym, że stara się dopasować jak najmniej, a nie tak bardzo, jak to możliwe. Spróbuj dodać znak:
w komentarzu, aby zobaczyć, dlaczego ma to znaczenie. -
\)
, aby zakończyć podgrupę. -
:
dopasowuje literał:
Następnie zastępujemy to tekstem chcesz i użyj \1
, aby odnieść się do grupy, którą przechwyciliśmy.
Wymyśliłem coś, używając tester wyrażeń regularnych
Składnia wyrażeń regularnych jest trochę podobna do składni wiki: jest ich kilka, na pierwszy rzut oka wszystkie wyglądają podobnie, żadne z nich jest oczywiście lepszy niż jakikolwiek inny, ale jest wiele różnic.
Obecnie tak zwane wyrażenia regularne „kompatybilne z Perlem” są de facto domyślnymi w większości języków, ale wyrażenia regularne Vima nie są kompatybilne z wyrażeniami zgodnymi z Perl! Składnia wyrażeń regularnych Vima sięga co najmniej „70”, kiedy Perla nie było nawet w pobliżu.
Możesz to zobaczyć w podgrupach, w których musisz użyć \(
a nie (
(jest to zgodne z „podstawową” składnią POSIX, ale nie z bardziej powszechną „rozszerzoną” składnią POSIX lub składnią Perla).Możesz to kontrolować, dodając we wzorcu flagę \v
(patrz :help /\v
aby uzyskać szczegółowe informacje), dzięki temu będzie bardziej kompatybilny, ale nie do końca (na przykład nadal musisz używać .{-}
dla niechcianych dopasowań)
To może wyjaśniać, dlaczego użycie „testera wyrażeń regularnych” działa prawie, ale nie do końca.
http://www.vimregex.com/ jako dobry przegląd / ściągawka do wyrażeń regularnych Vima.
Komentarze
- Świetna odpowiedź, zwłaszcza dlaczego regex! = regex. Jeśli chodzi o wyszukiwanie i zamianę, ' jest nieco skomplikowane, ponieważ komentarz może zawierać
:
lub nie. Zobacz pełny plik, aby uzyskać szczegółowe informacje github.com/squarefrog/dotfiles/blob/master/osx/…
Odpowiedź
Możesz:
- wyszukać wiersze, które się nie kończą w
#
::/[^#]$/
- zamień
#\s(.*)
na początku wiersz:s/\v^#\s(.*)/running "\1"/
Aby używać grup, musisz albo:
- zmienić znaczenie nawiasów, aby stają się częścią składni wyrażenia regularnego:
\(.*\)
lub - użyj „magic” przez rozpoczynając wyrażenie od
\v
:s/\v...
Łącząc:
:/[^#]$/s/\v^#\s(.*)/running "\1"/
Komentarze
- Działa to wspaniale, dziękuję za wyjaśnienie znaczenia tagów, a nie tylko tekst, którego potrzebowałem napisz.
- Dziękuję za wyjaśnienie, że nawiasy mają t o zostać wyłączone, aby stać się częścią składni wyrażenia regularnego. Zawsze miałem problem z grupami wyrażeń regularnych przy ich uruchamianiu.
:%s/\v\n\n#\s+(.*)/^M^Mrunning "\1"/
(dodano ” magiczne ” flaga). To naprawdę trudne do wybrania poprawna odpowiedź na moje pierwotne pytanie, ale czuję, że jest ona najbliższa mojej pierwotnie oczekiwanej odpowiedzi. Jest także jedynym, który działa w całym pliku bez konieczności wybierania zakresu.\r
zamiast^M
, aby uzyskać nowe linie?