Cercare e sostituire
La ricerca in Vim non serve solo a trovare: è un movimento come w o
}, quindi si combina con gli operatori. E :s è il
comando che, imparato bene, sostituisce mezz'ora di lavoro manuale.
Trovare
| Comando | Effetto |
|---|---|
| /testo | cerca in avanti |
| ?testo | cerca all'indietro |
| n N | occorrenza successiva / precedente, nella stessa direzione |
| * # | cerca la parola sotto il cursore, avanti / indietro |
| g* g# | come sopra, ma trova anche le parole che la contengono |
| /testo/e | ferma il cursore alla fine della corrispondenza |
| // | ripete l'ultima ricerca senza riscriverla |
Trattandosi di un movimento, funziona come argomento di un operatore:
d/FINE cancella da qui fino alla prima occorrenza di «FINE»,
y?inizio copia all'indietro. È il modo più diretto per lavorare su
regioni che non hanno un oggetto di testo.
Le quattro opzioni da mettere subito nel .vimrc
| Opzione | Cosa cambia |
|---|---|
| :set incsearch | evidenzia mentre digiti, prima di premere Invio |
| :set hlsearch | lascia evidenziate tutte le occorrenze |
| :set ignorecase | ignora maiuscole e minuscole |
| :set smartcase | …tranne se scrivi almeno una maiuscola: allora torna sensibile |
Le ultime due si usano insieme: errore trova tutto,
Errore trova solo la forma con la maiuscola. Per spegnere
l'evidenziazione quando dà fastidio: :noh (abbreviazione di
:nohlsearch) — non disattiva l'opzione, pulisce solo lo schermo.
Le regex di Vim, in breve
Vim usa una sintassi di espressioni regolari tutta sua, imparentata con le POSIX ma non identica a quelle di grep o Perl. La differenza pratica è che molti metacaratteri vanno preceduti da una barra rovescia:
| Scrivi | Significa |
|---|---|
| . * ^ $ [ ] | come ovunque: carattere qualsiasi, ripetizione, inizio, fine, classe |
| \+ \? \{2,5} | uno o più · zero o uno · da due a cinque |
| \| | alternativa fra due pattern |
| \( \) | gruppo, richiamabile poi con \1, \2… |
| \< \> | inizio / fine di parola |
| \d \w \s | cifra · carattere di parola · spazio |
| \zs \ze | segnano dove la corrispondenza inizia e finisce davvero |
\v. Messo all'inizio del
pattern attiva la modalità very magic, in cui i metacaratteri si scrivono
come in Perl o in grep -E: /\v(gatto|cane)+ invece di
/\(gatto\|cane\)\+. Su pattern complessi risparmia una selva di
barre.
Il comando :s pezzo per pezzo
:%s/vecchio/nuovo/gc │ │ │ │ │ │ │ └── flag: g = tutte le occorrenze della riga │ │ │ c = chiedi conferma ogni volta │ │ └──────── sostituto │ └──────────────── pattern da cercare └─────────────────────── intervallo di righe
Gli intervalli
| Intervallo | Righe interessate |
|---|---|
| (niente) | solo la riga corrente |
| % | tutto il file |
| 1,50 | dalla riga 1 alla 50 |
| .,$ | da qui alla fine |
| .,+10 | da qui alle dieci righe successive |
| '<,'> | la selezione visuale — appare da sola se premi : in VISUAL |
| /inizio/,/fine/ | dalla riga che contiene «inizio» a quella che contiene «fine» |
Esempi che vengono buoni davvero
# cambiare dominio in tutto il file, chiedendo conferma :%s/vecchiosito\.it/nuovosito\.it/gc # togliere gli spazi in fondo alle righe :%s/\s\+$//e # invertire "Cognome, Nome" in "Nome Cognome" usando i gruppi :%s/\v(\w+), (\w+)/\2 \1/ # numerare le righe non vuote :%s/^\(.\+\)$/\=line('.') . '. ' . submatch(1)/ # solo nelle righe che contengono TODO :%s/priorita: bassa/priorita: alta/g # incrementare tutti i numeri di versione di uno :%s/v\zs\d\+/\=submatch(0)+1/g
Nel sostituto valgono \1…\9 per i gruppi,
& per l'intera corrispondenza, \u e \U
per forzare maiuscolo (e \l, \L per minuscolo). Con
\= il sostituto diventa un'espressione VimScript, come nei due
esempi finali.
e serve più di quanto sembri. Senza,
:s che non trova nulla dà errore — e dentro una macro o un
:g l'errore interrompe tutto. Aggiungere e significa
«se non c'è, pazienza».
Pattern vuoto: cerca prima, sostituisci dopo
Le sostituzioni sbagliate nascono quasi sempre dallo stesso errore: scrivere un
pattern complicato dentro :%s/… e premere Invio sperando bene. Il
modo prudente è spezzare in due l'operazione — e Vim lo rende naturale, perché se
lasci il pattern vuoto riusa l'ultima ricerca.
/\v<utente_(\d+)> # 1. costruisci il pattern e guardalo evidenziato n n n # 2. verifica le corrispondenze una a una :%s//cliente_\1/g # 3. il pattern vuoto = "quello di prima"
I vantaggi sono tre: il pattern lo hai già visto funzionare con
hlsearch; non lo riscrivi, quindi non lo sbagli; e se qualcosa va
storto, un u annulla tutta la sostituzione in un colpo solo (è
un'unica modifica).
Due comodità che seguono dalla stessa idea
-
:%s//nuovo/gdopo aver premuto * su una parola: rinomina in tutto il file la parola sotto il cursore, senza digitarla. -
:&&ripete l'ultima sostituzione, flag compresi, sulla riga corrente. Con:%&&la ripete su tutto il file — utile dopo aver aperto un secondo file su cui serve la stessa modifica.
:%s/pattern//gn — con il
flag n — non sostituisce nulla e ti dice quante corrispondenze e
quante righe ha trovato. È il modo più rapido di rispondere a «quante volte
compare questa cosa nel file?».