Właśnie jestem po trzygodzinnym blitzkriegu Open Power Forms + Open Power Template. Sporo czasu zmarnowałem na pozornie prosty problem: jak podzielić taki ciąg: tekst tekst tekst; tekst tekst tekst; tekst "alala ; bebe" mo; lololo według średników, ale tylko tych nieznajdujących się w cudzysłowach. Dotychczas OPT robił to ręcznie, ale obsługiwał jedynie cudzysłowy, natomiast apostrof już nie (ewidentne niedopatrzenie). W każdym razie pierwsze próby polegały na układaniu wyrażeń regularnych, które by się tym zajęły. Prawdopodobnie jednak ich napisanie jest niemożliwe z technicznego punktu widzenia, a przynajmniej mi się za Chiny nie udało tego wykonać.
Później przyszedł mi bardzo dobry pomysł, aby wykorzystać technikę dzielenia na tokeny. Otrzymany w wyrażeniu wynik wprawdzie wymaga dodatkowego przetworzenia, ale jest to już tylko mała formalność w porównaniu z tym, co było. Oto, co wykombinowałem:
<?php $rDoubleQuoteString = '"[^"\\\\]*(?:\\\\.[^"\\\\]*)*"'; $rReversedQuoteString = '`[^`\\\\]*(?:\\\\.[^`\\\\]*)*`'; $rSingleQuoteString = '\'[^\'\\\\]*(?:\\\\.[^\'\\\\]*)*\''; $text = 'mamamama; dkdkdkd; jmdjkd "fkfk;fgfdg"; kfkf `dklj;` kjdlkj; djhfk \'dkjd;\' dsf'; echo '<pre>'; preg_match_all('/(?:'. $rDoubleQuoteString.'|'. $rSingleQuoteString.'|'. $rReversedQuoteString.'|;|[^"\'`;]*)/x', $text, $found); $params = array(0 => ''); $i = 0; foreach($found[0] as $item) { if($item == ';') { $i++; $params[$i] = ''; } else { $params[$i] .= $item; } } print_r($params); echo '</pre>'; ?>
Mamy tu pięć grup tokenów: teksty w cudzysłowach, apostrofach i odwróconych apostrofach, średniki oraz pozostały tekst. W wyniku znajdują się pasujące do nich elementy. W pętli wystarczy tylko łączyć je w jeden ciąg, a w przypadku napotkania średnika zacząć tworzyć nowy. Ot, cała filozofia, a tyle zachodu.
Na pocieszenie (rany, czyje? Na pewno nie moje!) dodam, że jeszcze trzeba podobną sztuczkę zrobić z dzieleniem całego szablonu na znaczniki i tekst statyczny. Włączcie sobie tryb kompatybilności z XML'em, parsując taki szablon:
<opt:if test="$obiekt->pole">test</opt:if>
Podpowiem, że OPT za znacznik weźmie tę część: <opt:if test="$obiekt-> i wyświetli błąd o... nieprawidłowej liczbie parametrów. Najprawdopodobniej podobnie się stanie z nawiasami klamrowymi. W dokumentacji PHP trafiłem na takie wyrażenie:
/(<(?:[^<>]+(?:"[^"]*"|\\'[^']*\\')?)+>)/
do zastosowania z preg_split. Według autora działa. Nie omieszkam tego sprawdzić, a jeżeli wypali, poeksperymentuję w tym kierunku.















Napisał hwao w poniedziałek, 9 stycznia 2006 o 21:19
tez sie zastanawialem czemu nie ma jakiegos parse_config(?) ;)