Fórumok
Egy adott mintában szeretném az összes @
karaktert :
karakterre cserélni, de kizárólag azokon a részeken, amit %%
és !%
stringek határolnak. Szemléltetem:
__ _ _ __ __ _ _ __ zj@fcavaszt%%rfcazr@tcc@cccc!%ccbfw@fcujw%%efcubzj@agew@ujca!%gewfcc@ccccaw zj@fcavaszt%%rfcazr:tcc:cccc!%ccbfw@fcujw%%efcubzj:agew:ujca!%gewfcc@ccccaw ^^ ^ ^ ^^ ^^ ^ ^ ^^
Végigtúrtam a netet, próbálkoztam saját kútfőből is, de nem jöttem rá a megoldásra. Valaki tudja esetleg?
Hozzászólások
Preg_replace_callbackkel egyszerű, tisztán Regexppel szerintem ez nem fog menni (éjfél van, régen volt a formális nyelvek, de gyanús, hogy ehhez más push-down automaton kéne)
BlackY
"Gyakran hasznos ugyanis, ha számlálni tudjuk, hányszor futott le már egy végtelenciklus." (haroldking)
Köszi, ez működik, bár pont ez volt a lényeg, hogy meg lehet-e tisztán regex-szel oldani.
Oldschool Computer - http://oscomp.hu
Ebben az esetben nekem Pythonban ez működött:
eutlantis
Működik az, csak akkor az ez történik:
Oldschool Computer - http://oscomp.hu
Arra gondoltam, hogy ez esetben az első kukacot nem kell cserélni, mert a szűken vett határolók nem %% és !%, hanem %% és %%.
eutlantis
A feladat csak az volt, hogy mindet cserélje, ami
%%
és a következő!%
között van. Lehet úgy is nézni, ahogy te nézed, de ez a bejövő adatnak magának a nesting hibája, amit nem az algoritmusból kell megkerülni, mert attól csak feleslegesen sokkal lassabb lesz; a bejövő adat maga hibás: nem egyértelműsíti, hogy hol akarja nyitni a cserélendő szakaszt; mi van, ha valójában pont a második%%
van rossz helyen és nem az első? Ennek megfelelően a kimenet igazából bármelyik értelmezésben helyes, de az első esetben sokkal gyorsabb.Oldschool Computer - http://oscomp.hu
Ha JavaScriptben kellene írnom akkor callback-kel csinálnám:
PHP-ben ez a preg_replace_callback.
Gyanítom rekurzióval meg lehet csinálni egy kifejezéssel is, kérdés, hogy megéri-e a komplexitást a viszonylag olvasható kódból a nehezen olvasható regex kifejezésbe átvinni.
Köszi, belerakva SzBlackY kódjába
ez is működik és a benchmark alapján gyorsabb is valamivel: 19235 ms vs. 15816 ms / 10000000 iteráció.
> Gyanítom rekurzióval meg lehet csinálni egy kifejezéssel is, kérdés, hogy megéri-e a komplexitást a viszonylag olvasható kódból a nehezen olvasható regex kifejezésbe átvinni.
Pont ez lenne a lényeg, hogy meg lehet-e egy lépésből regex-szel csinálni és ha igen, akkor gyorsabb-e.
Oldschool Computer - http://oscomp.hu
A teljesség meg a szépség kedvéért Perlül:
perl -lpe 's/%%.*?!%/$&=~y|@|:|r/ge'
Köszi, de ennek a replace részét hogy írom át a
preg_replace
által emészthető patternre?Oldschool Computer - http://oscomp.hu
Nagyjából úgy, ahogy fent írták, str_replace-szel. A perlben az y avagy tr operátor való a buta, karakterenkénti cserére. De a trükk itt is az, hogy a /e módosító miatt a csere-részt nem stringként, hanem perl kifejezésként értékeli ki, azaz kódot hajt végre.
A PHP optimalizálásához nem értek, de arra tippelek, hogy ha a gyorsaság a fő célod (mert nagyon sokszor, nagyon gyakran kell ezt a cserét végrehajtanod), akkor jobb, ha egyáltalán nem használsz reguláris kifejezést, hanem írsz egy ciklust, amiben egy státuszváltozóval számon tartod, hogy épp a határoló karaktersorok között vagy-e, és aszerint cserélsz vagy nem.
Az eredeti kódom úgy nézett ki - bár nem egyesével iteráltam a karaktereket, hanem a natív
strpos
-sal kerestem a nyitó/záró stringeket egymás után (offsettel ofcoz) - de alulmaradt a benchmarkokban a regexhez képest.Oldschool Computer - http://oscomp.hu