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 $