Nahrazování
Jedním z nejčastěji používaných příkazů editoru ex je nahrazování.
Příkaz se nazývá s
(substitute) a má následující
tvar:
<řádky>s/
<co_hledat>/
<čím_nahradit>/
<volby>
Jako všechny ostatní začíná určením řádků, kterých se má nahrazení
týkat. Za příkazem s
se uvádějí dva řetězce, jako
obvykle vymezené lomítky. První určuje, jaký text má editor hledat, a druhý čím
jej nahradit.
Příklad:
Kdybych chtěl v celém textu nahradit řetězec
raz
řetězcemdva
, použil bych::%s/raz/dva/
Připomínám, že procento ztělesňuje všechny řádky souboru.
Takto triviální případ vás samozřejmě těžko ohromí, ale především při vyhledávání se ukazuje síla regulárních výrazů. Navíc je můžete používat hned na dvou místech: jednak ve specifikaci řádků (kde se má pravidlo použít), jednak v parametrech vyhledávání. Pokročilejší příklady uvedu později.
Volby
Účinek nahrazování lze ovlivňovat volbami, které se uvádějí za závěrečným
lomítkem. Nejčastěji používané jsou dvě: g
a c
.
Volba g
způsobí, že vim nahradí všechny
výskyty řetězce na řádku. Implicitně totiž nahrazuje pouze první z nich, takže
z řádku
raz raz raz dvá raz
(oblíbené vojenské zaklínadlo pro synchronizaci pochodujících) by příkaz
:s/raz/dva/
udělal
dva raz raz dvá raz
Teprve příkaz
:s/raz/dva/g
zajistí nahrazení všech slov a vznikne
dva dva dva dvá dva
Abych mluvil skutečnou pravdu, chování vim závisí na nastavení
parametru gdefault
. Pokud je zapnut (:set gdefault
), editor implicitně nahrazuje všechny výskyty
řetězce na řádku. Při použití volby g
pak bude
nahrazovat vždy jen první kousek na každém řádku. Vypnutý parametr (:set nogdefault
) pak zajistí výše popsané chování, které je
implicitní pro původní editor vi i řadu dalších programů systému
Unix.
Volba c
umožňuje potvrzování každé náhrady. Zadáte-li
:%s/raz/dva/gc
vim se pokusí nahradit všechny řetězce raz
v textu, ale
každý z nich nejprve předvede a dotáže se, zda jej má skutečně nahradit. Tato
vlastnost je velmi užitečná, pokud se necítíte silní v kolenou a máte jisté
obavy, že hledanému řetězci by mohlo vyhovět i něco navíc proti vašemu záměru.
Svou odpověď můžete vybírat z obvyklých možností:
y |
nahradit daný výskyt |
n |
ponechat tento výskyt v původním tvaru a pokračovat dál |
[Esc] nebo q |
ponechat tento výskyt v původním tvaru a ukončit nahrazování |
a |
nahradit tento a všechny následující výskyty |
Komplikovanější příklady
Kdysi jsem v jednom zdrojovém textu potřeboval všechny číselné údaje vydělit deseti. To vlastně znamená vyhledat všechna čísla a před poslední číslici do nich vložit tečku. Zmíněnou akci obstará příkaz
:%s/\([0-9]*\)\([0-9]\)/\1.\2/g
Hledá skupiny číslic a ty si díky mechanismu zapamatování (kulaté závorky s lomítkem) rozdělí vždy na dvě části. První je dlouhá podle potřeby a druhá obsahuje vždy právě jednu (poslední) číslici. V nahrazovacím řetězci jen zopakuje tyto zapamatované skupiny, avšak mezi ně vloží tečku.
Nedávno jsme měnili strukturu domácích adresářů uživatelů na disku. Pro každého uživatele obsahoval soubor informace o uživatelském jméně a domácím adresáři – například
PAVEL.SATRAPA,USR:HOME\KIT\SATRAPA
Soubor byl uspořádán abecedně podle uživatelských jmen. My jsme však
potřebovali seskupit uživatele podle kateder, které se projevují v cestě k
domácímu adresáři za adresářem HOME
(jakožto příslušník katedry
informačních technologií bydlím v adresáři KIT
). Potřebovali jsme
tudíž vycucnout dotyčné jméno adresáře a zapsat je jako první údaj na
řádku - abychom obdrželi
KIT,PAVEL.SATRAPA,USR:HOME\KIT\SATRAPA
Takový soubor pak stačí protáhnout standardním programem sort
a
členové jednotlivých kateder se rázem ocitnou pospolu. Potřebnou transformaci
obstará
:%s/^\(.*:HOME\\\)\([^\\]*\)/\2,\1\2
Při vyhledávání si příkaz zapamatuje vše od začátku řádku až po řetězec
:HOME\
(jelikož lomítko má speciální význam, musí se v hledaném
řetězci zdvojit). Pod číslem 2 se následně zapamatuje řetězec znaků,
odlišných od lomítka (jinými slovy celý název adresáře až po následující
lomítko). V nahrazovacím řetězci se nejprve vypíše tento název adresáře, za
ním čárka a pak beze změny obě zapamatované části textu. Zbytek řádku zůstane
zachován (hledaný regulární výraz se na něj nevztahuje).
© 2016 Pavel Satrapa