2013-11-13 3 views
1

У меня есть этот код:Ошибка PHP? Специальная ошибка письма

$reg = "^[a-zA-ZáčďéíľňóřťšúůýžÁČĎÉÍĽŇÓŘŤŠÚŮÝŽ]{3,20}$"; // At least 3 

$string = "šš"; // Only 2 letters 

echo preg_match("+".$reg."+", $string); 

«S» является специальным письмом из Чехии.

Это echos 1. Почему? Это ошибка PHP?

+2

Если вы ищете символы, отличные от ascii, вам нужно включить модификатор 'u' в свой шаблон регулярного выражения. – Spudley

+2

@wumm: + отлично: http://php.net/manual/en/regexp.reference.delimiters.php – Reeno

+0

@Reeno, похоже, странный выбор, хотя использование + в качестве разделителя означает, что вы можете Использовать + в регулярном выражении? – OGHaza

ответ

1

the manual Посмотрите, особенно функция подписи:

int preg_match (string $pattern , string $subject [, array &$matches [, int $flags = 0 [, int $offset = 0 ]]]) 

он возвращает INT, 0, если нет совпадений найдено, 1 для совпадений. Если вы хотите, чтобы эти матчи, присвоенные переменной, вам придется пройти третий аргумент:

if (preg_match($pattern, $string, $matches)) 
{//if it returns 1, preg_match is true 
    var_dump($matches); 
} 

Прибавьте к тому, что вы сопрягая не-ASCII символов, for which there is a special man page, too, вы можете найти его матчи с двумя символами вместо трех. Поэтому вам придется прибегнуть к юникодам для этих специальных символов. š м, например, соответствует /\u0160/.
Более подробную информацию о регулярных выражениях + юникодом can be obtained here
Unicode символы являются «шире» (они занимают больше байт), но есть utf8-совместимый модификатор: u:

var_dump(preg_match('+'. $pattern . '+u', $string, $matches)); 
var_dump($matches); 

Сказав, что: я «немного огляделся, потому что PCRE предлагает имена скриптов для соответствия всему алфавиту в Юникоде. Быстрый взгляд на вики, а также некоторые другие источники говорит мне, что, возможно:

/\p{Cyrillic}/ 

может работать, но кириллица не совсем то же самое, во всяком случае, на the bottom of this page, вы можете найти таблицу, содержащую все Юникода коды для чешского алфавита.

Ни в коем случае вы можете винить PHP для этого ;-)
Как и в сторону, нанизывание картина все хорошо, но есть более безопасный способ: use the preg_quote function:

string preg_quote (string $str [, string $delimiter = NULL ]) 

В вашей случае:

$pattern = preg_quote($reg, '+'); 
+2

Он должен вернуть 0, потому что он ищет не менее 3 символов, когда он проходит 2 –

+0

@STTLCU: Правильно, я добавил ссылки на документацию по юникоду, и я проверяю, есть ли имя сценария для чешский алфавит ... кажется, что нет, хотя –

2

Используйте u modifier. Это приведет к совпадению PCRE_UTF8.

echo preg_match("+" . $pattern . "+u", $string); 

Это вернет 0 для строки два символа, но 1, если есть 3-х символов.

В документации не объясняется, почему, и я не могу найти что-либо на PCRE_UTF8, что объясняет это просто. Если бы мне пришлось рисковать предположить, что {} относится к байтам по умолчанию, но символы с u включены.

+1

Вероятно, из-за количества символов в символах Юникода (т.е. кодирования с переменной шириной). –

0

Это зависит от того, как кодируются специальные символы. Если ваш php-файл хранится с однобайтовой кодировкой, он должен работать, но не если вы используете utf-8. Если ваш php-файл является utf-8, специальные символы на самом деле составляют несколько байтов. Каждый из них имеет действительный байт для соответствия в классе символов. То же самое верно для строки $ it.Попытка:

var_dump(strlen("šš")); // should output int(4) 

u Модификатор активирует режим Unicode/UTF-8 для шаблона PCRE и изменяет поведение.

$reg = "^[a-zA-ZáčďéíľňóřťšúůýžÁČĎÉÍĽŇÓŘŤŠÚŮÝŽ]{3,20}$"; 
$string = "šš";  
echo preg_match("(".$reg.")u", $string); 

Это позволяет использовать и другие функции.

$reg = "(^\\pL{3,20}$)u"; 
var_dump(preg_match($reg, "šš")); 
var_dump(preg_match($reg, "šššš")); 

\pL коротка для юникода характера собственности «письма». Вы можете посмотреть в PHP manual для получения дополнительных возможностей.

Смежные вопросы