s///g v kombinaci s (?<=)

Pavel ©merk xsmerk na informatics.muni.cz
Pátek Září 6 10:08:10 MEST 2002


David Olszyński wrote:

>>On Thu, Sep 05, 2002 at 11:24:59AM +0200, Pavel ©merk wrote:
>>>$ perl -e '$a = "baa\n"; $a =~ s/(?<=b)a/b/g; print $a'
>>>bba
>>>Ocekaval jsem vystup bbb, myslel jsem si, ze nejprve se nahradi prvni a
>>>a pak druhe a, kdyz to chci "Replace globally, i.e., all occurrences."
>>>Jak tohle funguje a kde se o tom da docist (v perlre a perlop jsem nic
>>>nenasel) -- perl si ten retezec nemeni pod rukama? Mel jsem za to, ze
>>>(zhruba a vagne receno) se posunuje po retezci, pokud najde match,
>>>nahradi a hleda dalsi match od mista, kde skoncil minuly, tady to ale
>>>vypada, jako by to hledal na nejake RO kopii.
> 
> Ta volba /g sice znamena "pro vsechny vyskyty", ale tim se musi myslet "pro 
> vsechny vyskyty v _puvodni_ hodnote".
> Podle me se to proste nemuze delat "in place", protoze treba vec jako
> $ perl -e '$a = "baa\n"; $a =~ s/(?<=b)/b/g; print "$a\n"'
> by pak asi generovala sama "b" a nikoliv "bbaa", jak je tomu ve skutecnosti.


Se musi myslet... jak je tomu ve skutecnosti. Ja bych se to ale radeji 
dozvedel nekde z dokumentace, nez nutne neuplnym pozorovanim nejake 
skutecnosti :-)


> Ja si to vzdy predstavoval tak, ze se nejdriv najdou vsechny shody a na konci 
> se vsechno najednou nahradi (i kdyz takto to Perl nejspis nedela, nevim).


To jako ze by si je nejak oznackoval? Nebo jak by to presne bylo 
implementovane? Se mi moc nezda.

> Jisty si ale nejsem, protoze jsem to taky nikde nenasel.
> Pokud by to nekdo vedel urcite a mel treba nejaky odkaz, byl bych moc rad.

Jo, jo, presne o to mi jde. ;-)

David Olszyński wrote:
 > To je myslim uplny nesmysl. Uz priklad v prvnim prispevku tohoto 
vlakna to
 > ostatne vyraci. Perl prave _nenahrazuje_ uz jednou nahrazene. Autor 
puvodniho
 > prispevku ocekaval, ze to tak delat bude a ja se mu snazil vysvetlit, 
proc si
 > myslim, ze to je mylna predstava.

Tim autorem myslis me? To bude nejake nepochopeni. Rozhodne neocekavam, 
ze by nahrazoval uz jednou nahrazene. Viz dale.

 > Ondrej Koala Vacha wrote:
 >>Ten musi
 >>vedet, ze je tak, a pouzit treba cyklus while. Kdyby to delal
 >>perl sam, pak by ho prosta zamena s/ba/ba/g uvedla do nekonecneho cyklu.

Samozrejme, ze nikoli. Perl postupuje po retezci a hleda ba. Najde a 
nahradi. Pak hleda dal, cili od prvniho znaku za prave nahrazenym ba 
(nezavisle na tom, cim ba nahradil). Je pravda, ze v manualu jsem tohle 
nikde nenasel, je to tusim ve Velbloudi knize. Navic si nemyslim, ze by 
moznost vzniku nekonecneho cyklu byla nejakym argumentem ;-)

 > No, zdravy rozum veli, ze i kdyby to ten Perl nahrazoval primo v 
prohledavanem
 > retezci, tak by se vzdy aspon posunul o patricny pocet znaku. Takze 
takto
 > definitivne ne.

Presne takto jsem si to predstavoval. V tom mem puvodnim prikladu se 
nejprve nalezne prvni a a nahradi za b. Pak se prohledava zbytek 
retezce, tedy druhe a. To by ovsem opet mohlo splnovat podminku (?<=b)a 
a mohlo by tedy byt nahrazeno.

Zkusil jsem si vygenerovat mnohaMB retezec a pak v nem pripadne delat 
nejake s///g; Velikost zabrane pameti zustavala stale stejna, takze bud 
si zadnou kopii nedela (to by mi ale prislo neprakticke pro nahrady, 
ktere nejak meni delku), nebo prepisuje stary retezec do noveho vcetne 
pripadnych nahrazeni a zaroven stary umazava, aby setril pamet. Nebo to 
dela uplne jinak :)

P.



Daląí informace o konferenci Perl