Portál AbcLinuxu, 19. dubna 2024 08:00


Dotaz: PHP: Regulární výraz a diakritika v UTF-8

9.6.2009 15:44 N0rT0n | skóre: 9 | blog: Lama | Brno
PHP: Regulární výraz a diakritika v UTF-8
Přečteno: 4983×
Odpovědět | Admin

Zdravím,

řešil už někdo prapodivné chování PHP funkce mb_ereg() ?

regulární výraz

mb_ereg("^[a-zA-Z]*$","příšera")

se vyhodnotí negativně, zatímco regulární výraz

mb_ereg("^[a-zA-Z]*","příšera")

se vyhodnotí pozitivně (odstraněn znak pro konec řetězce).

Výraz:

mb_ereg("^[a-zA-Z]*$","prisera")

se vyhodnoti pozitivně.

 

Narazil jsem na tento problém při sestavování podstatně složitějšího výrazu, který u slov bez diakritiky fungoval naprosto bez problému. Problém je v tom, že ve výrazu nutně potřebuji omezit chování konec řetězce. Všechny patterny obsahující znak $ (pro konec řetězce) se vyhodnocují automaticky negativně.

Vstupem i výstupem je kódování UTF-8. mb_internal_encoding() hlasi UTF-8, mb_regex_encoding() taktéž. Tím, že řetězce na vstupu jsou v UTF-8, jsem si naprosto jist. Verze PHP je 5.2.6.

 

Má někdo nějaký nápad, či případně toto nějak řešil?

Nástroje: Začni sledovat (1) ?Zašle upozornění na váš email při vložení nového komentáře.

Odpovědi

9.6.2009 16:01 Blondak
Rozbalit Rozbalit vše Re: PHP: Regulární výraz a diakritika v UTF-8
Odpovědět | | Sbalit | Link | Blokovat | Admin

mb_ereg("^[a-zA-Z]*","příšera")
se vyhodnocuje správně pozitivně, protože souhlasí "p" na začátku, pokud budeš dělat
mb_ereg("^[a-zA-Z]*","činka")
tak to už vyhodnotí negativně, možná bych zkusil
preg_match("/^[\S]*$/u","příšera")
, ale nevím co přesně máš na vstupech.

9.6.2009 17:41 Ash | skóre: 53
Rozbalit Rozbalit vše Re: PHP: Regulární výraz a diakritika v UTF-8
se nevyhodnocuje správně pozitivně proto, že souhlasí "p" na začátku, ale proto, že výrazu ^[a-zA-Z]* vyhovuje jakýkoliv řetězec, který má začátek (to má každý) a pak náseduje 0 až N výskytů a-zA-Z. Takže by vyhovovala i šíšera.
10.6.2009 04:01 zha
Rozbalit Rozbalit vše Re: PHP: Regulární výraz a diakritika v UTF-8
Takže by vyhovovala i šíšera.

Měla by, ale proč neprojde ta činka?
10.6.2009 07:39 Ash | skóre: 53
Rozbalit Rozbalit vše Re: PHP: Regulární výraz a diakritika v UTF-8
činka projde
10.6.2009 10:56 Blondak
Rozbalit Rozbalit vše Re: PHP: Regulární výraz a diakritika v UTF-8

jj, pravda nějak jsem si spletl * a +

Tarmaq avatar 9.6.2009 16:31 Tarmaq | skóre: 39
Rozbalit Rozbalit vše Re: PHP: Regulární výraz a diakritika v UTF-8
Odpovědět | | Sbalit | Link | Blokovat | Admin
je to jak kolega pise v tom, ze v prvnim pripade se ten regular vyhodnoti jen na p
nevim jestli je to uplne koser reseni, ale slo by to asi udelat nejak takto:
setlocale(LC_CTYPE, 'cs_CZ.utf8');
$foo = iconv('utf-8', 'ascii//TRANSLIT', "příšera");

# mb_ereg se vyhodnoti pozitivne
mb_ereg("^[a-zA-Z]*$", $foo);

# jinak lze pouzit i tento tvar
mb_ereg("^[[:alpha:]]*$", $foo);
Don't panic!
9.6.2009 17:24 Sinuhet | skóre: 31
Rozbalit Rozbalit vše Re: PHP: Regulární výraz a diakritika v UTF-8
Odpovědět | | Sbalit | Link | Blokovat | Admin
preg_match("/^\p{L}*$/", "příšera");
9.6.2009 17:40 N0rT0n | skóre: 9 | blog: Lama | Brno
Rozbalit Rozbalit vše Re: PHP: Regulární výraz a diakritika v UTF-8
Odpovědět | | Sbalit | Link | Blokovat | Admin

Díky za reakce,

ten nápad s iconv mě taky napadl. Leč jsem si stále myslel, že mě napadne něco elegantního. V tom skriptu se jedná o ošetření vkládání klíčových slov. Pravidla jsou taková, že mohou začínat libovolným písmenem, mohou obsahovat číslici, od sebe jsou odděleny čárkou (či případně čárkou a mezerou) a musí končit slovem. Žádné jiné znaky nejsou povoleny, takže nelze použít třídu [[:alpha:]]. Vše až na to ošetření konce slova jsem už zvládl.

Správně by se měl vyhodnotit tento řetězec (i s vloženou frází "sportovní náčiní"):

činka, sportovní náčiní, číslo21, google

chybně by se měl vyhodnotit řetězec obsahující například:

činka, sportovní náčiní, 21. století, google,

(slovo nesmí začínat číslicí, tečka není přípustná a řetězec nesmí končit žádným jiným znakem, než [a-zA-Z0-9]). Něco jako

^[a-zA-Z0-9]*(,| )*[a-zA-Z0-9]*$
9.6.2009 19:16 N0rT0n | skóre: 9 | blog: Lama | Brno
Rozbalit Rozbalit vše Re: PHP: Regulární výraz a diakritika v UTF-8
Odpovědět | | Sbalit | Link | Blokovat | Admin

Moc elegantní to není, ale snad by to mohlo pomoci někomu, kdo podobný problém řeší:

$foo = iconv('utf-8', 'ASCII//IGNORE', $text);
if(ereg('^([a-zA-Z]{1,}[0-9]*(,| ){0,1})*[a-zA-Z]{1,}[0-9]*$',$foo)) {

  $result=1;

} else { $result=0; }

/*

1) do proměnné $foo se překóduje text z proměnné $text, která je kódována v UTF-8, proměnná $foo je nyní reprezentována v kódování ASCII s tím, že znaky, které nemohly být zkonvertovány do ASCII "tiše" zmizí (zajišťuje příznak //IGNORE)

2) klíčová slova musí začínat písmenem a případně končit číslicí, mezi slovy je přípustná čárka (oddělovač klíčových slov) nebo mezera (oddělovač slov v slovní frázi). Celý regulární výraz musí končit slovem (případně slovem s číslicí na konci).

*/

 Vypadá to, že to funguje, že jsem neudělal chybu (po 11 hodinách v práci by mě to ani nepřekvapilo).

 

Založit nové vláknoNahoru

Tiskni Sdílej: Linkuj Jaggni to Vybrali.sme.sk Google Del.icio.us Facebook

ISSN 1214-1267, (c) 1999-2007 Stickfish s.r.o.