Perl - nahrazení části textu v XML souboru

Jakub Řihák

Perl - nahrazení části textu v XML souboru
« kdy: 09. 08. 2012, 13:32:27 »
Dobrý den, snažím se v Perlu napsat skript, který by prošel všechny XML soubory v zadaném adresáři, každý z nich otevřel a prohledal ho, zda obsahuje zadaný text (porovnávání pomocí regulárního výrazu) a následně tento vyhledaný text nahradil jiným. Zatím se mi podařilo vše, až na zapsání změněného text do příslušného souboru. Zkoušel jsem vyhledaný text nahradit pomocí substituce přímo v regulárním výrazu. Pro kontrolu jsem si nechal vypsat nalezený text i text nahrazený, ale žádná změna se v souborech neobjevila. Mohl bych vás poprosit o radu? Kód vypadá následovně:

Kód: [Vybrat]
my $adresar=<STDIN>;
my (@soubory, $jmeno, $cesta);
 
chomp ($adresar);

opendir(ADR,$adresar) # otevírá adresář (dle zadané cesty)
    or die "Nelze otevrit $adresar!\n";

@soubory = readdir(ADR);   # načítá obsah adresáře do pole @soubory
closedir(ADR);




# pro každý soubor v adresáři porovná jména s regexpem (pokud jméno začíná
# tečkou, tak přeskočí na další a vytvoří pomocí proměnných $jmeno a $adresar
# celou cestu k souboru v zadané složce
foreach $jmeno (@soubory) {
  if ($jmeno =~ /^\./){
      next;
  }   

  $cesta=$adresar."\\".$jmeno;

  print "$jmeno\t".$cesta."\n";

  chomp ($cesta);

# otevře soubor umístěný v daném adresáři (cesta k němu je v proměnné $cesta)

  open (FOXML,$cesta)
    or die "Nemohu otevrit soubor $cesta\n";

# kontrolní výpis

  print "Oteviram soubor............. $cesta\n\n";

# pokud najde ve vstupním souboru řádek odpovídající regexpu nahradí ho jiným
# regexpem a pro kontrololu ho vypíše do konzole
  while ($radek=<FOXML>) {
    if ($radek=~ s/\<kramerius:file\>(\D{2,3})(\d{2}\D{1})(\d{3})(\d{3})(\_\d{4}).jpg\<\/kramerius:file\>/\<kramerius:tiles-url\>http:\/\/imageserver.techlib.cz\/$1\/$2\/$3\/$4\/$1$2$3$4$5.jp2\<\/kramerius:tiles-url\>/g ) {       
      print "$radek\n\n";       
    }
  }
}

# zavírání souboru
   
close (FOXML);


Pavel

Re:Perl - nahrazení části textu v XML souboru
« Odpověď #1 kdy: 09. 08. 2012, 14:00:11 »
Jste si jisty ze tu zmenu do toho souboru take zapisujete? V kodu akorat menite obsah promenne do ktere je obsah radku nacteny.

Jakub Řihák

Re:Perl - nahrazení části textu v XML souboru
« Odpověď #2 kdy: 09. 08. 2012, 14:08:38 »
To je pravda, zkoušel jsem tu proměnnou zapisovat do toho souboru nějak takhle:

Kód: [Vybrat]
while ($radek=<FOXML>) {
    if ($radek=~ s/\<kramerius:file\>(\D{2,3})(\d{2}\D{1})(\d{3})(\d{3})(\_\d{4}).jpg\<\/kramerius:file\>/\<kramerius:tiles-url\>http:\/\/imageserver.techlib.cz\/$1\/$2\/$3\/$4\/$1$2$3$4$5.jp2\<\/kramerius:tiles-url\>/g ) {       
      print "$radek\n\n";
      print FOXML <$radek>;

Ale asi to tak jednoduché nebude, že? (protože když ten zápis do souboru zapíšu takhle, tak se také nic nezmění)

aaaaaaaaaaaaa

Re:Perl - nahrazení části textu v XML souboru
« Odpověď #3 kdy: 09. 08. 2012, 14:19:50 »
To treba zapisat do suboru - obycajne sa pouziva zapis do ineho suboru, ako mate, aby bola zaloha starej verzie a az nakoniec sa subory nahradia.

A mimochodom, parsovanie XML pomocou regexpu je ZLO, ktore v 90% pripadov funguje len nahodou pre par spravnych vstupov, v 9% pripadov funguje ale nikto to nedokaze zarucit a vlastne ani porozumiet regexpu a v 1% pripadov nefunguje a ani nie je mozne vymysliet vymysliet regexp, s ktorym by to fungovalo.

Jakub Řihák

Re:Perl - nahrazení části textu v XML souboru
« Odpověď #4 kdy: 09. 08. 2012, 14:57:02 »
A je nějaká možnost, jak změnu zapsat do aktuálně otevřeného souboru na místo nelezené pomocí toho regulárního výrazu? Mohl bych vás eventuelně poprosit o ukázku kódu? Právě, že bych dost nerad "kopíroval" celé XML do nového souboru, jen proto, abych nahradil jeho malou část...


Re:Perl - nahrazení části textu v XML souboru
« Odpověď #5 kdy: 09. 08. 2012, 17:08:19 »
Jaký máš důvod nepoužít sed -i ?

Kit

Re:Perl - nahrazení části textu v XML souboru
« Odpověď #6 kdy: 09. 08. 2012, 21:44:47 »
A je nějaká možnost, jak změnu zapsat do aktuálně otevřeného souboru na místo nelezené pomocí toho regulárního výrazu? Mohl bych vás eventuelně poprosit o ukázku kódu? Právě, že bych dost nerad "kopíroval" celé XML do nového souboru, jen proto, abych nahradil jeho malou část...

Pokud nepracuješ s databází, tak se prakticky vždy kopíruje (se změnami) celý soubor do nového souboru a ten se následně přejmenuje. Pokud tedy potřebuješ takovou funkčnost, použij databázi.

Petr

Re:Perl - nahrazení části textu v XML souboru
« Odpověď #7 kdy: 09. 08. 2012, 22:41:51 »
A je nějaká možnost, jak změnu zapsat do aktuálně otevřeného souboru na místo nalezené pomocí toho regulárního výrazu? Mohl bych vás eventuelně poprosit o ukázku kódu? Právě, že bych dost nerad "kopíroval" celé XML do nového souboru, jen proto, abych nahradil jeho malou část...
Jak si představuješ, že to operační systém udělá? Pokud budou původní a nahrazovaný řetězec stejně dlouhé, může jen ten kousek "přepsat přímo na disku". Pokud ale bude jediný byte přebývat/chybět, musí být stejně zapsány VŠECHNY následující byte až do konce souboru. Zde navrhovaný postup čtu: z A, zapisuji do B, hotovo, smažu A, přejmenuji B na A ber jako obvyklý, vhodný, jediný možný.