11. 5. 1999 | ![]() ![]() ![]() ![]() ![]() |
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/public_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:
P°φklady
:g/HREF="http://www.domena.org/~uzivatel/adresar//s//HREF="../../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.org/~uzivatel/adresar/ 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
Leo╣ Literßk
literakl@seznam.cz
Linux Hardware
Autor: Leo╣ Literßk (jinΘ Φlßnky tohoto autora)
Sekce: Praxe
Souvisejφcφ Φlßnky:
11. 5. 1999 09:13:04 - Jde to i elegantneji. Misto '... (Petr Brouzda)
Jde to i elegantneji. Misto 'vi' pouzit 'sed' a je to na
jednu dlouhou prikazovou radku zacinajici findem.
PB.
11. 5. 1999 12:48:07 - Re: Jde to i elegantneji. Misto '... (Ond°ej Solansk²)
Nebo vyu╛φt pro nahrazovßnφ jenom Perl:
#!/usr/bin/perl
while (glob('*.html')) {
open (SOURCE,$_) or die '$!\n';
print 'Zpracovßvßm soubor ','$_,'\n';
open (TARGET, ')$_.new') or die '$!\n';
while ((SOURCE)) {
chomp;
s/nejaky text/za nejaky text/g;
print TARGET $_,'\n';
};
close SOURCE;
close TARGET;
}
while (glob('*.new')) {
$old = $_;
s/\.new//;
rename $old,$_;
}
11. 5. 1999 12:56:29 - Re: Jde to i elegantneji. Misto '... (Ond°ej Solansk²)
Poznßmka : Na °ßdcφch
open (TARGET, ')$_.new') or die '$!\n';
while ((SOURCE)) {
jsou vnit°nφ zßvorky ostrΘ, nikoliv kulatΘ, za co╛ nemohu - tak se to p°eneslo.
11. 5. 1999 14:47:03 - Za vsechny, kteri nepouzivaji ... (Jakub Steiner)
Za vsechny, kteri nepouzivaji sed a byl pro ne tento clanek nesmirne uzitecnym dekuji autorovi.
11. 5. 1999 17:07:17 - Mam k tomu clanku par poznamek... (Robert Wolf)
Mam k tomu clanku par poznamek:
A) zbytecne pouzivani perlu. stejne to lze udelat
i v shellu
for L in `find . -name *.html`;do sed -e '...';done
jedna radka a je to OK (u toho find jsou zpetny apostrofy)
a pokud to chcete jenom v aktualnim adresari,
tak staci pouze sed -e '...'
B) vetsina lidi asi pouziva Linux a obvykle RedHat
nevim jak jinde ale na RH je vi akorat link na vim
takze jestli ma vi a vim jiny regularni vyrazy, tak
to nebude fungovat, navic vim ma trosku odlisne
reg.vyrazy od perlu, takze pro perl se je ucte z
man perlre a pro vim se je ucte z helpu vimu
C) dalsi vec jsou priklady reg.vyrazu:
vyraz ma*ka v zadnem pripade (ani ve vimu ani v perlu)
nenajde slova matka, maska. totiz s reg.vyrazama je to
asi takhle:
. znak tecka zastupuje jakykoliv znak
* udava, ze se PREDCHOZI znak muze opakovat 0 a vickrat
+ udeva opakovani PREDCHOZIHO znaku 1 a vicekrat
? udava opakovani PREDCHOZIHO znaku 1 nebo 0 krat
{,n} predchozi znak se bude opakovat max. N-krat
{m,n} predch.znak se musi opakovat minimalne M-krat
a maximalne N-krat
{m,} znak se musi opakovat minimalne M-krat
{m} znak musi byt presne M-krat
pokud chcete opakovat posloupnost treba ABC,
tak se ta posloupnost uzavre do kulatych zavorek a
za zavorku se prida pocet, napr. (ABC){3,5} najde
posloupnost trojice ABC a to kdyz bude tahle trojice
za sebou trikrat az petkrat, cili
ABCABC ne
ABCABCABC jo
ABCABCABCABC jo
ABCABCABCABCABC jo
a delsi uz zase ne
pokud chcete nechat hledat znaky *,+,(,),/ atd.,
musite pred ne vlozit znak \, znak / se pouziva na
otevreni a uzavreni regularniho vyrazu, ale muzete misto
nej pouzit i jiny znak a pak muzete v reg.vyrazu pouzit
pouze znak / bez \. napr. pri hledani textu http://
je dobre pouzit vyraz
!http://! , kde zavorky reg.vyrazu bude znak vykricnik
je toho jeste vice, ale to by bylo opravdu na vlastni
clanek. Tohle totiz plati u PERLu,
VIM pouziva specialni znaky trosku jinak, napr.
co v PERLu znamena znak +, to se ve VIMu musi napsat
jako \+ atd. a take jeste zalezi na nastaveni
magic. Prostudujte skutecne man perlre, man grep,
man sed a help ve VIMu.
D) navic tenhle vyraz ma dve chyby:
g/HREF='http://www.domena.org/~uzivatel/adresar//s//HREF='/g
1) / nelze pouzit v reg.vyrazu, kdyz je / jako
zavorky reg.vyrazu. Musi se bud pouzit jine zavorky
nebo se pred znak / v reg.vyrazu musi zadat \
2) znak ~ ma ve vimu specialni vyznam, takze taky
potrebuje pred sebe znak \
E) pokud by nekdo chtel delat s vim a sed na MSDOS/WIN
tak muze, staci jit na adresy
ftp://ftp.vslib.cz/disk2/vim
a sed je v
ftp://ftp.zcu.cz/pub/simtelnet/gnu/djgpp/v2gnu/sed302b.zip
Zdravim
Wolf.
P.S.: Sorry za preklepy a pripadne chyby, ale melo
by to byt OK, ale nejsem regularni a VI guru:-)
takze chybicka se mozna vloudi
11. 5. 1999 17:16:32 - Re: Mam k tomu clanku par poznamek... (Robert Wolf)
Tady to pokracuje!!!!
Tohle totiz plati u PERLu,
VIM pouziva specialni znaky trosku jinak, napr.
co v PERLu znamena znak +, to se ve VIMu musi napsat
jako \+ atd. a take jeste zalezi na nastaveni
magic. Prostudujte skutecne man perlre, man grep,
man sed a help ve VIMu.
D) navic tenhle vyraz ma dve chyby:
g/HREF='http://www.domena.org/~uzivatel/adresar//s//HREF='/g
1) / nelze pouzit v reg.vyrazu, kdyz je / jako
zavorky reg.vyrazu. Musi se bud pouzit jine zavorky
nebo se pred znak / v reg.vyrazu musi zadat \
2) znak ~ ma ve vimu specialni vyznam, takze taky
potrebuje pred sebe znak \
E) pokud by nekdo chtel delat s vim a sed na MSDOS/WIN
tak muze, staci jit na adresy
ftp://ftp.vslib.cz/disk2/vim
a sed je v
ftp://ftp.zcu.cz/pub/simtelnet/gnu/djgpp/v2gnu/sed302b.zip
Zdravim
Wolf.
P.S.: Sorry za preklepy a pripadne chyby, ale melo
by to byt OK, ale nejsem regularni a VI guru:-)
takze chybicka se mozna vloudi
11. 5. 1999 17:24:16 - Re: Mam k tomu clanku par poznamek... (Robert Wolf)
A vloudila se chybicka:
V bode A) jsem chtel rict, ze pomoci sedu pouze v aktualnim adresari to jde pomoci prikazu
sed -e '...' *.html
kde ... je reg.vyraz neco jako
s!HREF='http;//www.server.org/\~uzivatel/!HREF='!gi
to g na konci znamena globalne-vickrat v jedne radce, coz se muze stat, ze na jedne radce bude vice odkazu
a to i znamena ignore-case, coz je dost dobre, protoze pokud nekdo zapise http misto HTTP, tak uz by to nas stary regularni vyraz nenasel
Wolf
![]() ![]() ![]() ![]() ![]() |