Hlavní navigace

Jak na hromadné nahrazování textu?

11. 5. 1999
Doba čtení: 5 minut

Sdílet

Určitě se vám již stalo, že jste potřebovali v několika souborech změnit text podle vám známého pravidla. Možná jste spustili svůj oblíbený textový editor a začali jste ručně nahrazovat výskyty textu XYZ textem ABC. Možná jste použili funkci Replace, zadali oba texty a pak jenom potvrzovali výměnu. Pokud těch souborů bylo několik (slovy méně než pět), pak se to dá zvládnout v rozumné době a při přijatelné námaze. Ale co když těch souborů je sto? Nebo padesát tisíc? Pro tento případ vám nabízím malý prográmek.

Tento prográmek se skládá ze dvou souborů – perlovského skriptu odstran a souboru s příkazy pro editor VI. Ne, nelekejte se, nebudete se muset učit pracovat s tímto klasickým editorem. Jen jej budeme využívat. V následujícím textu budu řešit problém odstranění absolutních adres v odkazech pro html soubory.

Skript
Perlovský skript je velice triviální. Vytvořte si soubor odstran (nebo použijte jiný název) a vložte do něj následující text: (tip pro začátečníky: tažením myši při stisknutém levém tlačítku text označte. Pak ve vedlejším okně či konzoli stisknutím prostředního tlačítka myši text vložíte do nějakého editoru.)

#!/usr/bin/perl
$soubory = `find . -name "*.html"`;
@file = split(/^/,$soubory);
foreach(@file)
{
        $neco = $_;
        chop $neco;
        print "Zpracovávám soubor $neco";
        system "vi -f -s /home/literakl/VI $neco";
}

Pak soubor uložte a nastavte u něj právo na spouštění (příkazem chmod +x odstran). Perlovští guru si možná budou rvát vlasy při pohledu na zdrojový kód nad jeho neefektivností, pro mně je ale důležité, že to funguje. Teď si jej trochu rozeberme. První řádek spouští interpretr perl. Pokud jej nemáte v adresáři /usr/bin, pak změňte cestu.

Na druhém řádku do proměnné $soubory vložíme všechny soubory, které našel program find. Tento program má obrovské možnosti, proto doporučuji přečíst si jeho manuálovou stránku (man find). Pro naše účely bude postačující následující popis.

První parametr určuje adresář, kde se má začít vyhledávat. V tomto případě tečka označuje aktuální adresář. Samozřejmě byste ale mohli použít absolutní cestu. Například /home/literakl/pu­blic_html/. Dalším parametrem je dvojice -name „*.html“. Tento parametr určuje, že se vyberou všechny soubory, jejichž jméno splňuje druhá část podle shellovské konvence. Tedy můžete použít zástupné znaky jako jsou například hvězdička (zastupuje nulu a více libovolných znaků), otazník (zastupuje přesně jeden libovolný znak) a hranaté závorky ([aeiouy] zastupuje jeden z vypsaných znaků, v tomto případě samohlásky, [^aeiouy] zastupuje jeden znak, který není v uvedemé množině). Takže v tomto případě se vyberou všechny soubory končící na .html v aktuálním adresáři a všech jeho podadresářích.

Ve zbylé části skriptu se jedna proměnná rozdělí do pole promměných a v cyklu se pro každý nalezený soubor vypíše jeho jméno a zpracuje programem vi. Část za znakem < samozřejmě nahraďte správnou cestou.

Soubor s příkazy
Do tohoto souboru se vkládají příkazy pro editor vi. Nazvěte si jej a umístěte, jak a kam chcete. Nezapomeňte pak ale upravit předposlední řádek skriptu. Text souboru VI má obecně následující tvar:

:g/XYZ/s//ABC/g
:wq

Na prvním řádku je regulární výraz, na druhém příkaz pro zapsání změn a ukončení činnosti editoru vi. Pokud vám regulární výrazy nic neříkají, zkuste spustit vi a v něm napsat :help pattern a zmáčknout enter. Jinou možností je manuálová stránka regulárních výrazů pro perl – man perlre.

Při běžné práci nahradíte text XYZ hledaným textem a ABC novým textem. Pokud se vám nechce pročítat manuály k regulárním výrazům (vřele doporučuji je přečíst), snad vám pomůže následující výtah, který má daleko k úplnosti.

XYZ může být běžný text, který hledáte. Potom algoritmus porovnává prošlý text s požadovaným textem a nalezne-li shodu, změní jej na ABC. V XYZ ale mohou být zástupné znaky. Hvězdička stejně jako v shellu nahrazuje libovolný počet libovolných znaků. Tečka nahrazuje jeden libovolný znak; tj. má stejný význam jako otazník v shellu. Hranaté závorky se chovají také stejně jako v shellu, vybírají jeden platný znak z uvedené množiny. Pokud chcete najít znak *,.,[ nebo ], napište před ním zpětné lomítko. To ruší význam speciálního znaku.

Příklady:

  • ahoj najde všechny slova obsahující ahoj.
  • ma*ka najde například maka, matka, maska, mařenka, ma7558kla atd.
  • ma.ka najde matka, mamka, maska, marka atd.
  • ma[mt]ka najde jen matka, mamka.
  • ma[^mt]ka najde maska, marka, ma8ka a další kromě matka a mamka.
  • ma[n-z]ka najde maska, marka, matka a další, kde prostřední písmeno leží v rozmezí n až z.
  • / najde všechna dopředná lomítka.
  • * najde hvězdičky.

Dalším speciální znakem je ^, pokud není použit jako negace ve výčtu znaků. Pak má význam začátku řádku. Obdobně znak $ ukazuje na konec řádku. Dvojice < je zase náhradou začátku slova a > pak konce slova.

Příklady

  • ^a na začátku řádky znak a
  • les$ na konci řádku znaky les
  • ^a$ na řádku je pouze znak a

To by snad mohlo pro úvod stačit. Teď se vrhněme zpátky na náš příklad. V html souborech, které jsme si stáhli, autor používá absolutní odkazy i s názvem jeho serveru. Jenže my nejsme připojeni na internet a tak nám prohlížeč píše, že nemůže najít ten server. A navíc přístup na disk je rychlejší než přes internet (pokud nesedíte u TEN-6000 :) ). Takže potřebujete odstranit například řetězec http://www.do­mena.org/~uzi­vatel/adresar/ v několika desítkách souborů. Soubor VI pak bude mít následující tvar:

:g/HREF=„http­://www.domena­.org/~uzivatel/a­dresarsHREF=“/g
:wq

Všimněte si zpětných lomítek rušících význam speciálních znaků. V části XYZ hledáme řetězec HREF=„http://­www.domena.or­g/~uzivatel/a­dresar/ a ten nahradíme řetězcem HREF=“. Tímto způsobem nahradíme skutečně jen odkazy, nikoliv text. Po spuštění skriptu odstran ve správném adresáři se nahradí všechny výskyty a za několik sekund je tato práce hotova.

Varování

Regulární výrazy mohou dělat něco jiného, než jste zamýšleli. Proto, pokud nejste guru přes regulární výrazy, raději si pořiďte záložní kopii dat. Varoval jsem vás.

Nevýhody

CS24_early

  • potřebujete rozumět regulárním výrazům
  • žádné uživatelské rozhraní
  • vše musíte napsat do obou souborů ručně


Výhody
  • vše musíte napsat do obou souborů ručně :)
  • automatizace nudných činností
  • efektivita práce prudce naroste (v určitých situacích)
  • regulární výraz nic nepřehlédne a nezapomene

Tento skript se hodí vždy, když potřebujete udělat nahrazení v mnoha souborech. Obvzláště se hodí při správě webovských stránek. Už se nebudete muset bát změny struktury adresářů na vašem rozlehlém webovském serveru. Pravda, něco podobného a příjemnějšího jsem nedávno viděl v Homesitu. Ani nevím, kdy to ode mne zkopírovali :). Snad to někomu pomůže.

Leoš Literák
literakl@seznam.cz
Linux Hardware

Byl pro vás článek přínosný?