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 34307×

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ů

4.10.2018 21:30 /Ondřej Čečák
LinuxDays 2018 již tento víkend, registrace je otevřená.
Přidat komentář

18.9.2018 23:30 /František Kučera
Zářijový pražský sraz spolku OpenAlt se koná již tento čtvrtek – 20. 9. 2018 od 18:00 v Radegastovně Perón (Stroupežnického 20, Praha 5). Tentokrát bez oficiální přednášky, ale zato s dobrým jídlem a pivem – volná diskuse na téma IoT, CNC, svobodný software, hardware a další hračky.
Přidat komentář

9.9.2018 14:15 /Redakce Linuxsoft.cz
20.9.2018 proběhne v pražském Kongresovém centru Vavruška konference Mobilní řešení pro business. Návštěvníci si vyslechnou mimo jiné přednášky na témata: Nejdůležitější aktuální trendy v oblasti mobilních technologií, správa a zabezpečení mobilních zařízení ve firmách, jak mobilně přistupovat k informačnímu systému firmy, kdy se vyplatí používat odolná mobilní zařízení nebo jak zabezpečit mobilní komunikaci.
Přidat komentář

12.8.2018 16:58 /František Kučera
Srpnový pražský sraz spolku OpenAlt se koná ve čtvrtek – 16. 8. 2018 od 19:00 v Kavárně Ideál (Sázavská 30, Praha), kde máme rezervovaný salonek. Tentokrát jsou tématem srazu databáze prezentaci svého projektu si pro nás připravil Standa Dzik. Dále bude prostor, abychom probrali nápady na využití IoT a sítě The Things Network, případně další témata.
Přidat komentář

16.7.2018 1:05 /František Kučera
Červencový pražský sraz spolku OpenAlt se koná již tento čtvrtek – 19. 7. 2018 od 18:00 v Kavárně Ideál (Sázavská 30, Praha), kde máme rezervovaný salonek. Tentokrát bude přednáška na téma: automatizační nástroj Ansible, kterou si připravil Martin Vicián.
Přidat komentář

18.6.2018 0:43 /František Kučera
Červnový pražský sraz spolku OpenAlt se koná již tento čtvrtek – 21. 6. 2018 od 18:00 v Kavárně Ideál (Sázavská 30, Praha), kde máme rezervovaný salonek. Tentokrát na téma: F-Droid, aneb svobodný software do vašeho mobilu. Kromě toho budou k vidění i vývojové desky HiFive1 se svobodným/otevřeným čipem RISC-V.
Přidat komentář

23.5.2018 20:55 /Ondřej Čečák
Od pátku 25.5. proběhne na Fakultě informačních technologií ČVUT v Praze openSUSE Conference. Můžete se těšit na spostu zajímavých přednášek, workshopů a také na Release Party nového openSUSE leap 15.0. V na stejném místě proběhne v sobotu 26.5. i seminář o bezpečnosti CryptoFest.
Přidat komentář

20.5.2018 17:45 /Redakce Linuxsoft.cz
Ve čtvrtek 31. května 2018 připravuje webový magazín BusinessIT ve spolupráci s Best Online Média s.r.o. pátý ročník odborné konference Firemní informační systémy 2018. Akce proběhne v kongresovém centru Vavruška (palác Charitas), Karlovo náměstí 5, Praha 2 (u metra Karlovo náměstí) od 9:00 hod. dopoledne do cca 15 hod. odpoledne. Konference je zaměřena na efektivní využití firemních informačních systémů a na to, jak plně využít jejich potenciál. Podrobnější informace na webových stránkách konfrence.
Přidat komentář

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

> Poslední diskuze

5.10.2018 17:12 / Jakub Kuljovsky
Re: Jaký kurz a software by jste doporučili pro začínajcího kodéra?

20.9.2018 10:04 / Jan Ober
Jaký kurz a software by jste doporučili pro začínajcího kodéra?

20.9.2018 10:00 / Jan Ober
Re: Gimp

20.2.2018 18:48 / Ivan Majer
portal

20.2.2018 15:57 / Jan Havel
Jak využíváte služby cloudu v podnikání?

Více ...

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