LINUXSOFT.cz Přeskoč levou lištu
Uživatel: Heslo:  
   CZUKPL

> Perl (21) - Regulární výrazy - nahrazování

Do této chvíle jsme regulární výrazy používali pouze k vyhledávání. To je ale jen polovina toho, co skutečně dokáží.

13.12.2005 06:00 | Jiří Václavík | Články autora | přečteno 33336×

Jak již o regulárních výrazech víme, slouží nejen pro vyhledávání vzorů, ale také pro nahrazování jejich částí. Představme si, že máme nějaký textový řetězec a potřebujeme z něj vymazat všechna čísla. Už známe několik způsobů, jak tento problém řešit. Celý řetězec by se dal rozdělit na znaky a každý získaný znak porovnat s možnými číslicemi. Další možností je rozdělit řetězec funkcí split s číselným oddělovačem. Nicméně to je všechno zbytečně pracné.

Regulární výrazy mají pro takové případy další možnou syntaxi. Chceme-li nahrazovat, použití regulárního výrazu se s prostým vyhledáváním v několika detailech liší. V zápisu se místo úvodního m používá s a jeho uvedení je povinné. Následuje vzor a řetězec, kterým bude úsek vyhovující vzoru nahrazen. Protože zde je o položku více, je třeba oddělovač navíc.

  s/vzor/náhrada/

Ač je zřejmé, že tomu nemůže být jinak, podotkněme, že náhrada je vždy prostým řetězcem a nikoliv regulárním výrazem.

V diskuzních fórech se dnes a denně setkáváme s reakcemi typu

  s/nabýdku/nabídku/

To je právě ukázka nahrazení, jen bez využití regulárních výrazů. Autor takového příspěvku dává na vědomí, že pisatel udělal pravopisnou chybu a měla by být opravena. Tímto způsobem bychom opravu řešili v Perlu:

  $reakce = "Takovou nabýdku nebudu komentovat...";
  $reakce =~ s/nabýdku/nabídku/;
  print $reakce; #tiskne opravený text

I kdyby bylo v řetězci více stejných chyb, opraví se jen jedna z nich. Vždy se nahrazuje pouze 1. výskyt. Po jeho nalezení totiž vyhledávání vzoru skočí úspěchem. Náš problém, kdy jsme chtěli z řetězce odstranit všechna čísla, by se dal řešit uvedením přepínače g. Ten se, podobně jako u vyhledávání, aplikuje na všechny výskyty vyhovující vzoru v řetězci. Výskyty tedy budeme nahrazovat prázdným řetězcem.

  $retezec = "P21E251215563R413215305711L587";
  $retezec =~ s/\d+//g;
  print $retezec; #tiskne PERL

Jednoduché nahrazování - konverze znaků

Tato problematika do regulárních výrazů nepatří, ale má s nimi některé společné rysy. Z tohoto důvodu je zařazena právě zde.

Činnost této konstrukce není nic jiného, než nahrazování konkrétního znaku (nikoliv regulárního výrazu) za jiný konkrétní znak.

Syntaxe je podobná jako při nahrazování u regulárních výrazů:

  $text =~ tr/abc/ABC/;
  $text !~ tr/abc/ABC/;
  $text =~ y/abc/ABC/;

y a tr jsou 2 synonymní zápisy.

Po vykonání libovolného ze zmíněných tří příkazů se obsah proměnné $text změní. Všechna a se nahradí za A, všechna b za B a všechna c za C. Obecně se tedy ntý znak na levé straně nahrazuje ntým znakem z pravé strany.

Rozdíl mezi použitím !~ nebo =~ je v návratové hodnotě. Výraz s !~ vrací true, pokud nedošlo k žádnému nahrazení. Pokud ano, vrací false. !~ se u tr příliš nepoužívá. Naproti tomu =~ vrací vždy počet nahrazení. Pokud je tento počet nenulový, návratová hodnota je tedy true.

I u tr fungují rozsahy. Není tak problémem v proměnné $text nahradit všechna malá písmena za velká, bez toho abychom je všechny vypisovali (pomiňme použití funkce uc):

  $text =~ tr/a-z/A-Z/;

Teď si objasníme sporné případy použití tr:

  • Pokud je na levé straně tentýž znak uvedený více než 1×, platí pouze 1. výskyt a ostatní jsou ignorovány.
  • Pokud je na levé straně více znaků než na pravé, jsou znaky na pravé straně příslušně doplněny. A to tak, že poslední znak pravé strany je naklonován, kolikrát je potřeba. Například:
      $text = "ABCDEF";
      $text =~ tr/A-F/xyz/;
      print $text;
    Výsledkem bude xyzzzz. Význam tr/A-F/xyz/ je stejný jako tr/A-F/xyzzzz/, protože znak z je příslušně nakopírován.
  • Pokud je na levé straně méně znaků než na pravé, je příslušný počet znaků na pravé straně zprava ignorován.
  •   $text = "ABCDEF";
      $text =~ tr/AB/xyz/;
      print $text;
    tr/AB/xyz/ má shodný význam se zápisem tr/AB/xy/, proto je tisknuto xyCDEF

Jako ukázku si nemohu odpustit Caesarovu šifru (v Unixu příkazy caesar, rot13). Jde o to nahradit každý znak (písmeno) znakem, který je v abecedě (ASCII tabulce, nebo zkrátka v nějaké soustavě znaků) o určitý počet znaků dále nebo blíže. Poprvé tuto šifru použili ke komunikaci Caesar a Cicero v době galské války. Písmena tehdy posouvali vždy o 3 znaky v abecedě dopředu.

Vytvoříme Caesarovu šifru s posunutím +4. Na vstupu (případně v souboru jako argumentu) bude program získávat otevřený text a následně vypisovat text šifrovaný.

K tomu potřebujeme cyklicky získávat řádky textu a zpracovávat je pomocí konstrukce tr. Posunutí +4 znamená, že a nahrazujeme za e, b za f, ..., v za z, w za a, x za b, y za c a z za d.

Takhle bude vypadat šifrovaná abeceda:

  Otevřená abeceda  abcdefghijklmnopqrstuvwxyz
  Šifrovaná abeceda (+4)  efghijklmnopqrstuvwxyzabcd

Otevřenou abecedu nahradíme šifrovanou:

  tr/abcdefghijklmnopqrstuvwxyz/efghijklmnopqrstuvwxyzabcd/;

Můžeme také využít rozsahy:

  tr/a-z/e-za-d/;

Vytvoříme cyklus, každou iteraci se načte řádek textu, provede se zašifrování a vytiskne se šifrovaný text:

  while ($radek = <>){
      $radek =~ tr/a-z/e-za-d/;
      print $radek;
  }

Také u tr lze pomocí výchozí proměnné vynechat operátor =~.

  while (<>){
      tr/a-z/e-za-d/;
      print;
  }

A abychom dovedli tuto ukázku téměř k dokonalosti, budeme nahrazovat i velká písmena:

  while (<>){
      tr/a-zA-Z/e-za-dE-ZA-D/;
      print;
  }

Přepínače

Pro tr existují dohromady 3 přepínače. V tabulce je jejich přehled.

PřepínačVýznam
sVíce stejných znaků za sebou, které mají být nahrazeny, jsou nahrazeny pouze 1 znakem.
cFunguje podobně jako negace hledaných znaků. Hledá a nahrazuje se jejich doplněk.
dNení-li dostatek znaků na pravé straně tr, nenahrazují se přebytečné znaky levé strany posledním znakem pravé strany, ale prázdným řetězcem.

Přepínač s

  $text = "xxxxyxx";
  $text =~ tr/x/X/s;
  print $text;

Podřetězce 'xxxx' a 'xx', jsou každý nahrazeny pouze jedním znakem X. Je tak vytisknuto 'XyX'.

Přepínač c

  $text = "xxxxyxXXxx";
  $text =~ tr/A-Z/ /c;
  print $text;

Bez uvedení přepínače by byla nahrazena všechna velká písmena mezerou. Protože zde ale je c, nahrazuje se vše mimo velkých písmen a tiskne se '      XX  '. V případné kombinaci s přepínačem s by výsledkem byl řetězec ' XX '

Přepínač d

  $text = "ABCDEFGH";
  $text =~ tr/ABC/x/d;
  print $text;

Vytisknuto je jen 'xDEFGH'. Hledáme znaky ABC, z nich pro B a C nemáme náhradu, a protože je uveden přepínač d, budeme je nahrazovat prázdným řetězcem. V případě, že by zde přepínač d nebyl, B a C by se nahrazovaly stejně jako A znakem x.

Počet výskytů znaku v řetězci

Protože výraz s operátorem =~ vrací počet nahrazení, vrací zároveň počet původních i nových znaků. Pokud tedy nahrazujeme znak stejným znakem, žádné změny v řetězci nenastanou. Pouze získáme počet výskytů. Řádek kódu přiřazuje do proměnné $vyskytu počet výskytů znaku x v obsahu proměnné $text:

  $vyskytu = $text =~ tr/x/x/;

Příště budeme pokračovat přepínači a speciálními konstrukcemi v perlových regulárních výrazech.

Verze pro tisk

pridej.cz

 

DISKUZE

caesarova sifra 13.12.2005 11:01 Ondrej Hanousek
  L Re: caesarova sifra 13.12.2005 12:36 Jan Houštěk




Příspívat do diskuze mohou pouze registrovaní uživatelé.
> Vyhledávání software
> Vyhledávání článků

14.11.2017 16:56 /František Kučera

Máš rád svobodný software a hardware nebo se o nich chceš něco dozvědět? Zajímá tě DIY, CNC, SDR nebo morseovka? Přijď na sraz spolku OpenAlt – tradičně první čtvrtek před třetím pátkem v měsíci: 16. listopadu od 18:00 v Radegastovně Perón (Stroupežnického 20, Praha 5).


Přidat komentář

12.11.2017 11:06 /Redakce Linuxsoft.cz
PR: 4. ročník odborné IT konference na téma Datová centra pro business proběhne již ve čtvrtek 23. listopadu 2017 v konferenčním centru Vavruška, v paláci Charitas, Karlovo náměstí 5, Praha 2 (u metra Karlovo náměstí) od 9:00. Konference o návrhu, budování, správě a efektivním využívání datových center nabídne odpovědi na aktuální a často řešené otázky, např Jaké jsou aktuální trendy v oblasti datových center a jak je využít pro vlastní prospěch? Jak zajistit pro firmu či jinou organizaci odpovídající služby datových center? Podle jakých kritérií vybrat dodavatele služeb? Jak volit součásti infrastruktury při budování či rozšiřování vlastního datového centra? Jak efektivně spravovat datové centrum? Jak eliminovat možná rizika? apod.
Přidat komentář

13.9.2017 8:00 /František Kučera
Máš rád svobodný software a hardware nebo se o nich chceš něco dozvědět? Zajímá tě DIY, CNC, SDR nebo morseovka? Přijď na sraz spolku OpenAlt – tentokrát netradičně v pondělí: 18. září od 18:00 v Radegastovně Perón (Stroupežnického 20, Praha 5).
Přidat komentář

3.9.2017 20:45 /Redakce Linuxsoft.cz
PR: Dne 21. září 2017 proběhne v Praze konference "Mobilní řešení pro business". Hlavní tématy konference budou: nejnovější trendy v oblasti mobilních řešení pro firmy, efektivní využití mobilních zařízení, bezpečnostní rizika a řešení pro jejich omezení, správa mobilních zařízení ve firmách a další.
Přidat komentář

15.5.2017 23:50 /František Kučera
Máš rád svobodný software a hardware nebo se o nich chceš něco dozvědět? Zajímá tě DIY, CNC, SDR nebo morseovka? Přijď na sraz spolku OpenAlt, který se bude konat ve čtvrtek 18. května od 18:00 v Radegastovně Perón (Stroupežnického 20, Praha 5).
Přidat komentář

12.5.2017 16:42 /Honza Javorek
PyCon CZ, česká konference o programovacím jazyce Python, se po dvou úspěšných ročnících v Brně bude letos konat v Praze, a to 8. až 10. června. Na konferenci letos zavítá např. i Armin Ronacher, známý především jako autor frameworku Flask, šablon Jinja2/Twig, a dalších projektů. Těšit se můžete na přednášky o datové analytice, tvorbě webu, testování, tvorbě API, učení a mentorování programování, přednášky o rozvoji komunity, o použití Pythonu ve vědě nebo k ovládání nejrůznějších zařízení (MicroPython). Na vlastní prsty si můžete na workshopech vyzkoušet postavit Pythonem ovládaného robota, naučit se učit šestileté děti programovat, efektivně testovat nebo si v Pythonu pohrát s kartografickým materiálem. Kupujte lístky, dokud jsou.
Přidat komentář

2.5.2017 9:20 /Eva Rázgová
Putovní konference československé Drupal komunity "DrupalCamp Československo" se tentokrát koná 27. 5.2017 na VUT FIT v Brně. Můžete načerpat a vyměnit si zkušenosti z oblasti Drupalu 7 a 8, UX, SEO, managementu týmového vývoje, využití Dockeru pro Drupal a dalších. Vítáni jsou nováčci i experti. Akci pořádají Slovenská Drupal Asociácia a česká Asociace pro Drupal. Registrace na webu .
Přidat komentář

1.5.2017 20:31 /Pavel `Goldenfish' Kysilka
PR: 25.5.2017 proběhne v Praze konference na téma Firemní informační systémy. Hlavními tématy jsou: Informační systémy s vlastní inteligencí, efektivní práce s dokumenty, mobilní přístup k datům nebo využívání cloudu.
Přidat komentář

   Více ...   Přidat zprávičku

> Poslední diskuze

18.9.2017 14:37 / Rojas
high security vault

15.9.2017 7:33 / Wilson
new zealand childcare jobs

31.8.2017 12:11 / Jaromir Obr
Re: ukůládání dat ze souboru

30.7.2017 11:12 / Jaromir Obr
Národní znaky

27.7.2017 12:24 / Jaromir Obr
Cteni/zapis

Více ...

ISSN 1801-3805 | Provozovatel: Pavel Kysilka, IČ: 72868490 (2003-2017) | mail at linuxsoft dot cz | Design: www.megadesign.cz | Textová verze