O čem si budeme povídat?
Zpracování textu patří mezi nejb>žn>jší programátorské činnosti. Díky tomu nám v>tšina programovacích jazyků nabízí řadu specifických nástrojů, které mají zpracování textu usnadnit. V této části se podíváme na n>které z nich a na to, jak je můžeme využít při realizaci typických programátorských úloh.
Mezi nejb>žn>jší akce při práci s textem patří:
Podíváme se, jak se uvedené úkoly řeší v jazyce Python. Poté se stručn> seznámíme s tím, jaké možnosti zpracování textu poskytují jazyky VBScript a JavaScript.
Od verze 2.3 Python při zpracování textu postupuje trošku nejednoznačn>.
Příčina spočívá v tom, že starší verze jazyka Python provád>ly veškeré
manipulace prostřednictvím modulu, který byl nap>chovaný funkcemi a
užitečnými konstantami. Python verze 2.0 zavedl pro typ řet>zec metody,
které nahrazují funkce ve zmín>ném modulu, ale konstanty byly dostupné stále
jen prostřednictvím modulu. Tato situace trvala až do verze 2.3. Další vývoj
sm>řuje k tomu, aby potřeba používat starý modul string byla
zcela odstran>na. V tomto tématu se zam>říme výlučn> na nový, objektov>
orientovaný přístup k manipulaci s řet>zci. Pokud si chcete vyzkoušet práci
s původním modulem, hledejte potřebné informace v jeho dokumentaci.
Nejdříve se budeme zabývat tím, jak můžeme řet>zec rozd>lit na části, z kterých se skládá. Při zpracování textových souborů se s takovým požadavkem setkáváme často. Obsah souboru se obvykle snažíme číst po řádcích, ale požadovaná data mohou být uložena v určitých částech řádků. Jako příklad si můžeme uvést náš záznamník s adresami. Místo tisku celé adresy bychom mohli chtít přistupovat například jen k částem adresy.
V Pythonu pro tento účel použijeme metodu split() (rozd>lit na části,
rozštípnout) následujícím způsobem:
>>> retezec = 'Toto je (kratky) retezec.' >>> print retezec.split() ['Toto', 'je', '(kratky)', 'retezec.']
Povšimn>te si, že se nám vrací seznam, který obsahuje slova z řet>zcové
prom>nné retezec. Všechny mezery byly odstran>ny.
Předdefinovaným odd>lovačem metody split() jsou totiž bílé
znaky (tj. tabulátory, znaky přechodu na nový řádek a mezery). Zkusme
to znovu, ale tentokrát si jako odd>lovač vybereme otvírací závorku:
>>> print retezec.split('(')
['Toto je ', 'kratky) retezec.']
Vidíte ten rozdíl? Seznam obsahuje tentokrát jen dva prvky a otvírací
závorka na začátku 'kratky)' byla odstran>na. Důležitou
vlastností metody split() je to, že odstraňuje odd>lovací
znaky. V>tšinou takové chování požadujeme, ale občas bychom si přáli, aby
tomu tak nebylo.
K dispozici máme i metodu join(), která přebírá seznam (nebo
také jinou podobu posloupnosti) řet>zců a spojuje je dohromady. Jednou z
matoucích vlastností metody join() je to, že řet>zec, jehož
metodu join() voláme, je použit v roli spojovacích znaků.
Následující příklad ukazuje, co mám na mysli:
>>> lst = ['Tohle', 'je', 'seznam', 'slov.'] >>> print '-+-'.join(lst) Tohle-+-je-+-seznam-+-slov. >>> print ' '.join(lst) Tohle je seznam slov.
Když o tom začnete přemýšlet, dává to smysl. Ale na první pohled to vypadá divn>.
Poznámka překladatele: Na první pohled by se zdálo přirozen>jší,
kdyby metoda join() byla metodou typu seznam a jako
parametr by přebírala řet>zec, který se použije pro spojení prvků seznamu:
>>> lst.join('-+-') # Tohle NEFUNGUJE!
Ale argumentem metody join() nemusí být přímo
seznam řet>zců. Může to být libovolný iterovatelný objekt, tj.
objekt který podporuje průchod jednotlivými řet>zcovými položkami. (Typicky
to bývá kontejner, ale může to být například i generátor s omezeným počtem
generovaných řet>zcových hodnot.) Pokud si to uv>domíme, nevypadá už
rozhodnutí o příslušnosti metody join() k řet>zcovému typu tak
nezvykle. V opačném případ> by metoda join() musela být
implementována pro všechny typy kontejnerů, jejichž obsah bychom cht>li
spojovat. Následující příklad uvádí převod seznamu na n-tici a na množinu a
spojení jejich obsahu mezerou:
>>> lst = ['Tohle', 'je', 'seznam', 'slov.'] >>> t = tuple(lst) >>> se = set(lst) >>> print ' '.join(t) Tohle je seznam slov. >>> print ' '.join(se) je seznam Tohle slov.
Povšimn>te si, že v případ> množiny není dodrženo pořadí, ve kterém se prvky množiny vkládaly (z množinového hlediska není pořadí položek důležité). Z prvků množiny ovšem můžeme n>jakou funkcí vytvořit uspořádanou posloupnost:
>>> print ' '.join(sorted(se)) Tohle je seznam slov.
Zdánliv> správné pořadí slov je dáno pouze náhodou, protože uvedená slova ve v>t> náhodou odpovídají svému lexikografickému pořadí. Dokažme si to na jiném příklad>:
>>> lst = ['tohle', 'je', 'neusporadany', 'salat', 'z', 'ceskych', ... 'slov', 'bez', 'diakritickych', 'znamenek'] >>> se = set(lst) >>> print ' '.join(se) ceskych slov neusporadany diakritickych znamenek bez salat je z tohle >>> print ' '.join(sorted(se)) bez ceskych diakritickych je neusporadany salat slov tohle z znamenek
Nyní se znovu podívejme na program pro počítání slov, o kterém jsem se zmínil v předchozí podkapitole o funkcích. Připomeňme si, že pseudo kód vypadal takto:
def pocetSlov(s):
seznam = split(s) # seznam, kde prvkem je vždy slovo
return len(seznam) # vrátíme počet prvků seznamu
for radek in soubor:
celkem = celkem + pocetSlov(radek) # sečti počty za každý řádek
print "Soubor má %d slov." % celkem
Nyní již víme, jak lze načítat řádky souboru. Podívejme se blíže na t>lo
funkce pocetSlov(). Nejdříve chceme z daného řádku vytvořit
seznam slov. Stačí, když na řádek aplikujeme standardní metodu
split(). Nahlédnutím do dokumentace zjistíme, že zabudovaná
funkce len() vrací pro seznam počet v n>m umíst>ných prvků. V
našem případ> to bude počet slov v řet>zci, což je přesn> to, co
potřebujeme.
Takže konečná podoba zdrojového kódu vypadá takto:
# -*- coding: cp1250 -*-
import string
def pocetSlov(s):
seznam = s.split() # split() je metodou řet>zcového objektu s
return len(seznam) # vrátíme počet prvků seznamu
vstup = open('menu.txt', 'r')
celkem = 0 # vytvoříme prom>nnou a nastavíme jí počáteční hodnotu nula
for radek in vstup:
celkem = celkem + pocetSlov(radek) # sečti počty za každý řádek
print u'Soubor má %d slov.' % celkem
vstup.close()
Tento program není tak docela správný, protože například započítá samostatn> stojící znak
'&' (ampersand) jako slovo (ačkoliv si vlastn> můžete myslet, že je to
správné). Program navíc zpracovává jediný soubor (menu.txt).
Ale není příliš obtížné upravit jej tak, aby jméno souboru četl z
příkazového řádku (argv[1]) nebo prostřednictvím
raw_input(), jak jsme si ukázali v podkapitole Konverzace s uživatelem. Řešení ponechávám za
domácí úkol.
Další b>žnou operací, na kterou se teď podíváme, je vyhledávání
podřet>zce v delším řet>zci. V Pythonu pro ni op>t nalezneme podporu v
podob> metody zabudovaného řet>zcového typu — tentokrát se jmenuje
find(). Její základní způsob použití je velmi jednoduchý.
Předáte jí vyhledávaný podřet>zec, a pokud jej Python v hlavním řet>zci
najde, vrátí index prvního znaku, na kterém podřet>zec začíná. Pokud
podřet>zec nalezen není, vrací se hodnota -1:
>>> retezec = 'Toto je dlouhy retezec, ve kterem se nachazi podretezec.'
>>> print retezec.find('dlouhy')
8
>>> print retezec.find('moc')
-1
>>> print retezec.find('retezec')
15
První dva příklady použití jsou přímočaré. První z nich vrací index
začátku podřet>zce 'dlouhy'. Druhý příklad použití vrací
hodnotu -1, protože podřet>zec 'moc' se v řet>zci
nevyskytuje. U třetího příkladu použití narazíme na jeden detail —
vyhledal se první výskyt zadaného podřet>zce. Ale co vlastn> můžeme
d>lat v případech, kdy se hledaný vzorek vyskytuje v původním řet>zci více
než jednou?
Jedna z možností spočívá v použití indexu prvního výskytu a rozseknutí
původního řet>zce na dv> části. Poté můžeme hledat znovu. Takto pokračujeme
až do doby, kdy se nám vrátí výsledek -1:
# -*- coding: cp1250 -*- retezec = u"'Haf, ňaf', říká pes. Kolik 'af' je v řet>zci?" s = retezec # Na začátku se odkazujeme na stejný řet>zec. pocet = 0 index = s.find('af') while index != -1: pocet += 1 s = s[index + 1:] # Budeme pracovat s druhou částí řet>zce (slicing). index = s.find('af') print u"V řet>zci \"%s\" jsme našli %d výskyty vzorku 'af'." % (retezec, pocet)
V příkladu jsme pouze výskyty vzorku pouze počítali. Stejn> dobře bychom ale mohli nalezené indexy sbírat do seznamu, který bychom využili při dalším zpracování.
Pokud použijeme nepovinné parametry metody find(), můžeme
proces urychlit. T>mito nepovinnými parametry je určení počáteční a koncové
pozice v původním řet>zci:
# -*- coding: cp1250 -*- retezec = u"'Haf, ňaf', říká pes. Kolik 'af' je v řet>zci?" pocet = 0 index = retezec.find('af') while index != -1: pocet += 1 start = index + 1 # Připravíme nový začátek. index = retezec.find('af', start) print u"V řet>zci \"%s\" jsme našli %d výskyty vzorku 'af'." % (retezec, pocet)
U tohoto řešení nemusíme pokaždé vytvářet nový řet>zec, což může být v případ> dlouhých řet>zců časov> náročné. Pokud chceme vyhledávat výskyt podřet>zce jen v n>kolika prvních znacích (a další případné výskyty nás nezajímají), můžeme určit počáteční a koncové pozice prohledávané části řet>zce takto:
# -*- coding: cp1250 -*-
retezec = u"'Haf, ňaf', říká pes. Kolik 'af' je v řet>zci?"
print retezec.find('af', 0, 20)
V souvislosti s vyhledáváním Python nabízí navíc n>kolik p>kných, speciálních
metod, které se nám hodí v nejčast>jších případech — jde zejména o
metody startswith() a endswith() (dalo by se přeložit jako
začíná tímhle a končí tímhle). Samotná jména
napovídají, so metody asi d>lají. Vracejí hodnoty True nebo
False v závislosti na to, zda původní řet>zec (tj. objekt jehož metodu
voláme) začíná nebo končí vyhledávaným podřet>zcem. Příklad:
>>> print 'Python jede!'.startswith('Perl')
False
>>> print 'Python jede!'.startswith('Python')
True
>>> print 'Python jede!'.endswith('je nanic!')
False
>>> print 'Python jede!'.endswith('de!')
True
Povšimn>te si, že výsledek je boolovského typu. Povšimn>te si také, že
vyhledávací řet>zec nemusí mít podobu celého slova, stačí prost> podřet>zec.
Pokud chcete testovat na výskyt podřet>zce jen v učité části řet>zce, můžeme
upřesnit počáteční a koncovou pozici části, která se má prohledávat —
stejn> jako u metody find(). V praxi se ale tenhle rys moc
nepoužívá.
Na záv>r si uveďme, že pro prosté otestování, zda se podřet>zec nachází
kdekoliv v řet>zci můžeme použít pythonovský operátor in
takto:
>>> if 'foo' in 'foobar': print 'True' True >>> if 'baz' in 'foobar': print 'True' >>> if 'bar' in 'foobar': print 'True' True
Poznámka překladatele: Podle mého názoru uvedený příklad zbytečn> kombinuje přímo nesouvisející v>ci a svádí tak začátečníky na scestí.
if.True, pokud je výsledek výrazu True
navozuje představu, že jinak to není možné ukázat.Za didaktičt>jší pokládám přímé zobrazení výsledku výrazu:
>>> print 'foo' in 'foobar' True >>> print 'baz' in 'foobar' False >>> print 'bar' in 'foobar' True
Liší se to sice tím, že se v druhém případ> tiskne False,
zatímco v původním příkladu se netiskne nic, ale asi to není na závadu. V
interaktivním režimu můžeme dokonce vynechat příkaz print:
>>> 'foo' in 'foobar' True >>> 'baz' in 'foobar' False >>> 'bar' in 'foobar' True
K vyhledávání je to zatím vše. Teď se podívejme, jak můžeme provád>t náhrady textu.
Když nalezneme hledaný podřet>zec, často jej chceme zm>nit na n>co
jiného. Řešení se nám nabízí v podob> metody replace(), kterou
nalezneme mezi metodami pro pythonovský typ řet>zec. Vyžaduje zadání dvou
argumentů: vyhledávaný podřet>zec a řet>zec, kterým bude nahrazen. Metoda
vrací nový řet>zec, který je výsledkem náhrady.
>>> retezec = 'Jedna, dv> / Honza jde / nese pytel s brouky'
>>> print retezec.replace('s brouky', 'mouky')
Jedna, dv> / Honza jde / nese pytel mouky
Zajímavé je, že metoda replace() standardn> nahrazuje
všechny výskyty vyhledaného řet>zce a ne jen první výskyt, narozdíl
od metody find(). (Není to zase tak překvapující, pokud si
uv>domíme, že find() by při vyhledávání všech výskytů musela
vracet seznam pozic. Bráno z opačného konce, u metody replace()
— pokud by nahrazovala standardn> jen první výskyt — bychom zase
n>jakým způsobem museli um>t předepsat náhradu všech výskytů.)
Maximální počet náhrad můžeme omezit zadáním nepovinného argumentu
count (tj. počet):
>>> retezec = 'Haf, ňaf, blaf, řekl pejsek.'
>>> print retezec.replace('af', 'afiky')
Hafiky, ňafiky, blafiky, řekl pejsek.
>>> print retezec.replace('af', 'afiky', 1) # jen první výskyt
Hafiky, ňaf, blaf, řekl pejsek.
Mnohem důmysln>jší operace vyhledávání a náhrad můžeme provád>t pomocí nástroje zvaného regulární výrazy. Ale práce regulárními výrazy je mnohem složit>jší, a proto si zaslouží vlastní téma v části Témata pro pokročilé.
Poslední v>c, kterou se v této části budeme zabývat, je zm>na malých písmen na velá a naopak. Není to tak úpln> b>žná operace, ale Python nám pro tento účel nabízí pár metod:
>>> print u'SMÍšenÝ PŘípad: >ščřžýáíéúůó ĚŠČŘŽÝÁÍÉÚŮ'.lower() smíšený případ: >ščřžýáíéúůó >ščřžýáíéúů >>> print u'SMÍšenÝ PŘípad: >ščřžýáíéúůó ĚŠČŘŽÝÁÍÉÚŮ'.upper() SMÍŠENÝ PŘÍPAD: ĚŠČŘŽÝÁÍÉÚŮÓ ĚŠČŘŽÝÁÍÉÚŮ >>> print u'SMÍšenÝ PŘípad: >ščřžýáíéúůó ĚŠČŘŽÝÁÍÉÚŮ'.swapcase() smíŠENý přÍPAD: ĚŠČŘŽÝÁÍÉÚŮÓ >ščřžýáíéúů >>> print u'SMÍšenÝ PŘípad: >ščřžýáíéúůó ĚŠČŘŽÝÁÍÉÚŮ'.capitalize() Smíšený případ: >ščřžýáíéúůó >ščřžýáíéúů >>> print u'TEST'.isupper() True >>> print u'TEST'.islower() False
Povšimn>te si, že metoda capitalize() (z anglického capital letter,
čili velké písmeno) provádí zv>tšení prvního písmene pro řet>zec jako
celek, nikoliv pro každé slovo zvlášť. Všimn>te si také dvou funcí pro
otestování řet>zce na určitou vlastnost (neboli predikátů). K dalším užitečným
testům patří isalpha() a isspace(). Poslední
zmín>ná funkce kontroluje, zda se v řet>zci vyskytují jen bílé
znaky, tedy nejen mezery (tj. také tabulátory, konce
řádků...).
V dalších částech kurzu budeme mnohé z uvedených řet>zcových metod používat. Zejména Případová studie gramatického počítadla jich používá n>kolik najednou.
Poznámka překladatele: Povšimn>te si, že ve výše uvedené ukázce
řet>zcových metod jsou všechny literály (řet>zcové konstanty) zapsány jako
Unicode řet>zce — na začátku, před prvním apostrofem mají uvedeno
písmeno u. V originálním anglickém textu tomu tak není.
Ale čeština používá znaky, které nepatří do kódu ASCII, a proto význam kódu
znaku závisí na tom, jaké kódování používáme.
Pythonovský string, který není uložen v kódování Unicode, s sebou nenese
žádnou informaci o použitém kódování. Python takový řet>zec chápe jako
posloupnost bajtů. Nemá odkud vzít informaci o tom, že velké písmeno k znaku
s kódem 249 má kód 217. Například v kódování windows-1250 jde o
znaky ůŮ. V jiných kódováních ovšem uvedené kódy mohou patřit
zcela jiným znakům, nemusí vůbec tvořit pár malé/velké písmeno a dokonce
vůbec nemusí patřit mezi písmena.
ASCII znaky — tj. ty, které mají kód v rozsahu 0 až 127 — představují výjimku v tom smyslu, že mají stejný kód ve všech odvozených kódováních (kódy ASCII znaků jsou zachovány i v Unicode). Metody pro zm>nu velikosti písmen tedy mohou bez problémů nad t>mito znaky fungovat i bez znalosti používaného kódování pro písmena s v>tším kódem. Podívejme se, co Python provede, když bychom v příkladu neuvedli řet>zce v Unicode:
>>> print 'SMÍšenÝ PŘípad: >ščřžýáíéúůó ĚŠČŘŽÝÁÍÉÚŮ'.lower() smÍšenÝ pŘípad: >ščřžýáíéúůó ĚŠČŘŽÝÁÍÉÚŮ >>> print 'SMÍšenÝ PŘípad: >ščřžýáíéúůó ĚŠČŘŽÝÁÍÉÚŮ'.upper() SMÍšENÝ PŘíPAD: >ščřžýáíéúůó ĚŠČŘŽÝÁÍÉÚŮ >>> print 'SMÍšenÝ PŘípad: >ščřžýáíéúůó ĚŠČŘŽÝÁÍÉÚŮ'.swapcase() smÍšENÝ pŘíPAD: >ščřžýáíéúůó ĚŠČŘŽÝÁÍÉÚŮ >>> print 'SMÍšenÝ PŘípad: >ščřžýáíéúůó ĚŠČŘŽÝÁÍÉÚŮ'.capitalize() SmÍšenÝ pŘípad: >ščřžýáíéúůó ĚŠČŘŽÝÁÍÉÚŮ >>> print 'ĚŠČŘŽÝÁÍÉ'.islower() False >>> print 'ĚŠČŘŽÝÁÍÉ'.isupper() False
Všechna písmena v rozsahu ASCII jsou správn> převedena, ale všechna
ostatní písmena byla ponechána beze zm>ny. Metoda neví, co s nimi, proto je
ponechá v původním tvaru. Uv>domte si, že je to přirozené chování metod v
případech, kdy zpracovávají znaky, která nejsou písmenem. Existují také
písmena, která nemají definováno odpovídající malé nebo velké písmeno
(například n>mecké ostré s). Všimn>te si, že predikáty
islower() a isupper() zde nepovažují testované
řet>ze ani za malá ani za velká písmena.
Unicode řet>zce jsou ovšem speciáln>jší, informačn> bohatší. Písmena jsou určena jednoznačn> a existuje i jednoznačný vztah mezi malým a velkým písmenem (pokud to u znaku dává smysl). Metody pro převody písmen z malých na velká a naopak nemusí zohledňovat žádné nejednoznačnosti. Při použití Unicode se tedy i u ostatních lidských jazyků dostáváme do stejn> pohodové situace, v jaké o podobných řet>zcových operacích píší anglicky mluvící autoři ;-)
VBScript vychází z jazyka BASIC. Díky tomu disponuje celou řadou zabudovaných funkcí pro práci s řet>zci. V referenční příručce jsem jich napočítal nejmén> 20 a to jsem nepočítal ty, které se vztahují k zpracování znaků v Unicode.
To znamená, že v jazyce VBScript můžeme s řet>zci d>lat v podstat> vše, co jsme si ukazovali v jazyce Python. V rychlosti si ukážeme jeho možnosti:
Začneme funkcí Split:
<script type="text/vbscript">
Dim retezec
Dim seznam
retezec = "Toto je seznam slov."
seznam = Split(retezec) ' vrací pole
MsgBox seznam(1)
</script>
Pokud nám rozd>lování řet>zce v místech s bílými znaky (zde mezerami) nevyhovuje, můžeme stejn> jako v Pythonu předepsat hodnotu odd>lovače.
Pro opačný postup zde máme funkci Join — stejn> jako v
jazyce Python.
K vyhledávání podřet>zce slouží funkce InStr, což je zjevn>
zkratka z anglického In String, tedy
v řet>zci.
<script type="text/vbscript"> Dim s, n s = "Toto je dlouhý textový řet>zec." n = InStr(s, "dlouhý") MsgBox "Slovo 'dlouhý' bylo nalezeno na pozici: " & CStr(n) </script>
Návratová hodnota obvykle udává pozici v původním řet>zci, na které začíná
vyhledávaný podřet>zec. Pokud není nalezen, vrací se nula. (V jazyce VBScript
to nepůsobí žádný problém, protože se v n>m indexuje od jedničky. To znamená,
že hodnota nula nereprezentuje platnou hodnotu indexu.) Pokud má řet>zec
hodnotu Null, vrací se hodnota Null. Tím se pon>kud
komplikuje ov>řování, zda nedošlo k chyb>.
Stejn> jako v Pythonu můžeme i v jazyce VBScript vymezit část původního řet>zce, která se má prohledávat. Můžeme uvést index, od kterého se má začít vyhledávat:
<script type="text/vbscript">
Dim s, n
s = "Toto je dlouhý textový řet>zec."
n = InStr(6, s, "dlouhý") ' Hledej od pozice 6.
MsgBox "Slovo 'dlouhý' bylo nalezeno na pozici: " & CStr(n)
</script>
Narozdíl od Pythonu můžeme v jazyce VBScript předepsat také to, zda se mají při vyhledávání rozlišovat velká a malá písmena, či nikoliv. Pokud to neurčíme, velká a malá písmena se rozlišují.
Náhrady textu se provád>jí prostřednictvím funkce Replace:
<script type="text/vbscript"> Dim s s = "Příšern> zeleňoučký kůň úp>l ďábelské ódy." MsgBox Replace(s, "zeleňoučký", "žluťoučký") </script>
Poslední nepovinný argument určuje, kolik výskytů vyhledávaného vrorku se
má nahradit. Pokud neurčíme jinak, nahrazují se všechny výskyty. Můžeme určit
i počáteční pozici pro prohledávání a náhradu, jako u výše zmín>né funkce
InStr.
Zm>nu velikosti písmen provádíme v jazyce VBScript funkcemi
UCase a LCase. Ekvivalent pythonovské metody
capitalize() tady nenajdeme.
<script type="text/vbscript"> Dim s s = "SMÍšenÝ PŘípad: >ščřžýáíéúůó ĚŠČŘŽÝÁÍÉÚŮ" MsgBox LCase(s) MsgBox UCase(s) </script>
To je vše, čím se budeme v této učebnici zabývat. Pokud se chcete dozv>d>t více, projd>te si seznam funkcí v nápov>d> k VBScript.
Poznámka překladatele: V tomto případ> (narozdíl od stejného řet>zce v pythonovském příkladu, kdy řet>zec nebyl uveden v Unicode) dojde ke korektnímu převodu na malá i velká písmena i u znaků s diakritikou. Je to dáno tím, že VBScript s řet>zci jednoznačn> spojuje určité kódování. Pokud je skript vložen do HTML souboru, pak bývá kódování předepsáno v jeho hlavičce. Stejn> je tomu i u XML souborů. Pokud kódování není předepsáno vůbec, pak VBScript předpokládá, že se používá kódování definované v systému.
JavaScript je z našich tří jazyků pro zpracování textu vybaven nejhůře. I přesto jsou základní operace do určité míry podporovány. Ve srovnání s jazyky Python a VBScript jazyk JavaScript trpí nedostatky, které tkví spíše jen v množství "cingrlátek". JavaScript tato omezení kompenzuje silnou podporou regulárních výrazů. (Budeme se jimi zabývat v jednom z dalších témat.) Regulární výrazy výrazn> rozšiřují možnosti, které poskytují výše zmín>né primitivní funkce, ale platíme za to zvýšením složitosti.
JavaScript, stejn> jako Python, využívá k manipulaci s řet>zci objektov>
orientovaný přístup. Všechny operace se provád>jí prostřednictvím metod
třídy String.
Rozd>lování textu se provádí metodou split():
<script type="text/javascript">
var seznam, retezec = "Toto je krátký řet>zec";
seznam = retezec.split(" ");
document.write(seznam[1]);
</script>
Povšimn>te si, že JavaScript vyžaduje zadání odd>lovacího znaku. Neexistuje zde žádná předdefinovaná hodnota. Odd>lovač může být definován i regulárním výrazem, takže operace rozd>lení může být velmi důmyslná.
K vyhledávání textu se v jazyce JavaScript používá metoda
search():
<script type="text/javascript">
var retezec = "Na Nilu ibisi kvílili bílí...";
document.write("'ibisi' se nachází na pozici: " + retezec.search(/ibisi/));
</script>
zmatky řet>zec/vzorek
Znovu platí, že vyhledávaný řet>zcový vzorek je ve skutečnosti regulárním výrazem. To znamená, že vyhledávání může mít velmi důmyslná pravidla. Na druhou stranu neexistuje možnost vymezit část původního řet>zce, která se má prohledávat, zadáním počáteční pozice (ačkoliv i tuto možnost můžeme simulovat prostřednictvím regulárního výrazu).
JavaScript podporuje i jinou vyhledávací operaci s mírn> odlišným
chováním. Nazývá ze match() ([meč], zde ve smyslu odpovídat,
pasovat). V této částí se metodou match()
nebudeme zabývat.
zmatky řet>zec/vzorek
K nahrazování textu se používá metoda replace().
<script type="text/javascript"> var retezec = "Kočka leze dírou, pes dveřmi..."; document.write(retezec.replace(/dveřmi/, "oknem")); </script>
A znovu připomeňme, že vyhledávaný vzorek může být zadán regulárním výrazem. Myslím, že už vidíte ten obecný vzor. Operace náhrady nahrazuje všechny výskyty vyhledávaného vzorku a, pokud mohu říci, neexistuje žádný způsob, jak dosáhnout náhrady pouze jednoho výskytu, aniž byste řet>zec nejdříve rozd>lili a pak jej op>t pospojovali dohromady.
zmatky řet>zec/vzorek, počet náhrad
Pro zm>nu velikosti písmen máme k dispozici dv> funkce:
toLowerCase() a toUpperCase().
<script type="text/javascript"> var retezec = "SMÍšenÝ PŘípad: >ščřžýáíéúůó ĚŠČŘŽÝÁÍÉÚŮ"; document.write(retezec.toLowerCase()+ "<br>"); document.write(retezec.toUpperCase()+ "<br>"); </script>
K t>mto funkcím můžeme st>ží co dodat. Jednoduchým způsobem provád>jí jednoduchou činnost. JavaScript — narozdíl od ostatních jazyků, o kterých se bavíme — nabízí řadu speciálních textových funkcí pro zpracování HTML. Odhaluje tím své kořeny jazyka určeného pro programování ve webovém prostředí. Nebudeme se jimi zabývat. Popis naleznete ve standardní dokumentaci.
Tím uzavíráme pohled do sv>ta zpracování textu. Doufám, že jste tím získali nástroje, které potřebujete ke zpracování textu ve vašich projektech. Záv>rečná rada zní: Při zpracování textu si vždy pročt>te dokumentaci zvoleného jazyka.Řešení nejzákladn>jších programátorských úloh je často podpořeno mocnými nástroji.
Zapamatujte si
readlines() jazyka Python přečte všechny řádky
souboru najednou, zatímco funkce readline() přečte jen jeden
řádek. Může nám to pomoci šetřit pam>tí.Pokud vás napadne, co by se dalo na překladu této kapitoly vylepšit, zašlete e-mail odklepnutím Tím budou do dopisu automaticky vloženy informace o tomto HTML dokumentu.
$Id: cztuttext.html,v 1.6 2005/10/20 20:52:40 petr Exp $