Am un fișier cu o grămadă de valori implicite ale utilizatorului. Vreau să schimb o parte din text, dar mă lupt venind cu un potrivitor și înlocuitor. Folosind următorul exemplu:
############################################################################### # 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
Aș dori să înlocuiesc # Trackpad: ...
cu running "Trackpad: ..."
Înlăturând problema, am venit cu ceva folosind un tester regex:
/\n\n#\s(.*)/g
Dacă încerc să folosesc acest lucru în Vim, nu funcționează pentru mine:
:/\n\n#\s(.*)/running "\1"/g
Cred că problema mea se rezumă la două întrebări specifice:
- Cum pot evita căutarea
\n
caractere și, în schimb, să mă asigur că#
nu apare la sfârșitul grupului de căutare? - Cum pot utiliza în mod eficient grupurile de captură?
Mai jos există câteva răspunsuri extraordinare. Greu de ales între toate cele trei, totuși consider că răspunsul ales este cel mai exact pentru specificațiile mele originale. Vă recomandăm să încercați toate cele trei răspunsuri cu fișierul real pentru a vedea ce părere aveți despre ele.
Răspuns
Doar pentru a fi clar … Cred că ați cerut ca acesta să fie rezultatul înlocuirii?
############################################################################### # 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
În acest caz, recomand următoarea comandă:
:%s/\n\n#\s\+\(.*\)/^M^Mrunning "\1"/
Explicația modelului
:s/PATTERN/REPLACEMENT/
este comanda substitut . Semnarea procentuală :%s
îl face să funcționeze pe întregul fișier, mai degrabă decât doar pe linia curentă.
\n\n
spune că linia de interes trebuie să apară după o linie goală. Dacă nu ți-ar păsa de linia goală precedentă, atunci ^
ar fi suficient.
#\s\+
se potrivește cu un hash caracter urmat de unul sau mai multe caractere în spațiu alb. \(.*\)
surprinde tot textul ulterior de pe linie.
Explicația textului de înlocuire
^M^M
introduce două capete de linii pentru a înlocui \n\n
care erau prezente în model. În caz contrar, textul ar fi mutat la sfârșitul liniei precedând linia goală. Pentru a tasta fiecare ^M
, apăsați Ctrl-V Ctrl-M .
Apoi, introduceți șirul running
, urmat de orice a fost capturat între paranteze în ghilimele duble.
Comentarii
Răspunde
Aș folosi ceva de genul:
:s/^#\s\+\(.\{-}\):/running "\1":/
-
^#
pentru a se potrivi cu caracterul#
ancorat la începutul liniei (aceasta răspunde la întrebarea 1) -
\s\+
pentru a potrivi orice spațiu alb de una sau mai multe ori -
\(
pentru a începe un grup (aceasta răspunde la întrebarea 2) -
.\{-}\
pentru a se potrivi cu orice caracter de 0 sau mai multe ori într-un mod non-lacom ; acest lucru este diferit de.*
prin faptul că încearcă să se potrivească cât mai puțin posibil și nu cât mai mult posibil. Încercați să adăugați un caracter:
în comentariu pentru a vedea de ce contează acest lucru -
\)
pentru a termina subgrupul. -
:
se potrivește cu un literal:
Apoi îl înlocuim cu textul doriți și utilizați \1
pentru a vă referi la grupul pe care l-am capturat.
Am venit cu ceva folosind un tester de regex
Sintaxa expresiei regulate este un pic ca sintaxa wiki: există o grămadă de ele, toate seamănă dintr-o privire, niciuna dintre ele este în mod evident mai bun decât oricare altul, dar există multe diferențe.
Astăzi, așa-numitele expresii regulate „compatibile Perl” sunt implicite de facto în majoritatea limbilor, dar expresiile regulate Vim nu compatibil cu expresiile compatibile cu Perl! Sintaxa Vim regexp se întoarce la cel puțin „70”, când Perl nu era chiar în jur.
Puteți vedea acest lucru cu subgrupurile, unde trebuie să utilizați \(
și nu (
(aceasta este compatibilă cu sintaxa POSIX „de bază”, dar nu cu sintaxa POSIX „extinsă” mai frecventă sau sintaxa Perl).Puteți controla acest lucru adăugând semnalizatorul \v
într-un model (A se vedea :help /\v
pentru detalii), acest lucru îl va face „mai compatibil”, dar nu complet (Trebuie să utilizați în continuare .{-}
pentru meciurile care nu sunt lacomi, de exemplu)
Deci, acest lucru ar putea explica de ce funcționează aproape un tester de regex.
http://www.vimregex.com/ ca o bună prezentare generală / foaie de cheats a Vim regexps.
Comentarii
- Răspuns excelent, mai ales cu motivul pentru care regex! = regex. În ceea ce privește căutarea și înlocuirea dvs., ‘ este puțin dificil, deoarece comentariul poate avea sau nu un
:
. Consultați fișierul complet pentru detalii github.com/squarefrog/dotfiles/blob/master/osx/…
Răspuns
Puteți:
- căuta linii care nu se termină în
#
::/[^#]$/
- înlocuiți
#\s(.*)
la începutul linia:s/\v^#\s(.*)/running "\1"/
Pentru a utiliza grupuri, trebuie să:
- să scapi de paranteze astfel încât devin parte a sintaxei regexului:
\(.*\)
sau - utilizați „magic” de începând expresia cu
\v
:s/\v...
Combinând-o:
:/[^#]$/s/\v^#\s(.*)/running "\1"/
Comentarii
- Acest lucru funcționează strălucit, mulțumesc că ați inclus o explicație a ceea ce înseamnă etichetele, mai degrabă decât doar textul de care aveam nevoie scrieți.
- Vă mulțumim că ați arătat clar că parantezele au t o să fie scăpat pentru a deveni parte a sintaxei regexului. Am avut întotdeauna o problemă cu grupurile regex în ceea ce privește punerea lor în funcțiune.
:%s/\v\n\n#\s+(.*)/^M^Mrunning "\1"/
(a adăugat magia ” magia ” pavilion). Este foarte greu de ales un răspuns corect pentru întrebarea mea originală, dar consider că acest răspuns este cel mai apropiat de răspunsul meu inițial așteptat. Este, de asemenea, singurul care funcționează pe întregul fișier fără a fi nevoie să selectați un interval.\r
în loc de^M
pentru a obține linii noi?