Ответ 1
Это действительное регулярное выражение, если вместо /
для разделителя используйте #
. Пример:
preg_match('#^('.$pattern.')$#', $value);
Похоже, что спецификация HTML5 (и, следовательно, ECMA262) позволяет <input type="text" pattern="[0-9]/[0-9]" />
соответствовать строке "0/0" даже хотя прямая косая черта не ускользает. Веб-приложения, такие как Drupal, хотели бы обеспечить проверку на стороне сервера для браузеров, которые не поддерживают HTML5, с чем-то вроде:
<?php
preg_match('/^(' . $pattern . ')$/', $value);
?>
К сожалению, строка '[0-9]/[0-9]' не является допустимым регулярным выражением PRCE. Похоже, что большинство, если не все браузер, поддерживающий HTML5, поддерживают как pattern="[0-9]/[0-9]"
, так и pattern="[0-9]\/[0-9]"
, который задает вопрос - что мы можем использовать в качестве разделителя для запуска этого шаблона с регулярным выражением в стиле Perl?
Мы подали отчет об ошибке против спецификации W3C, но являются ли здесь браузеры неправильными? Нужно ли уточнять спецификацию HTML5? Есть ли способ обхода, который мы можем использовать в PHP?
Это действительное регулярное выражение, если вместо /
для разделителя используйте #
. Пример:
preg_match('#^('.$pattern.')$#', $value);
Я рекомендую использовать "\xFF"
byte как разделитель шаблонов, потому что он не разрешен в строке UTF-8, поэтому мы можем быть уверены, что это не произойдет в шаблоне. И поскольку preg_match не понимает UTF-8, это не вызовет никаких проблем.
Пример: preg_match("\xFF$pattern\$\xFFADmsu", $subject);
Обратите внимание на модификаторы ADmsu
и добавьте $
. Модификатор u
требует действительных байтов UTF-8 только в шаблоне, но не в разделителях вокруг.
Одна из проблем с PCRE заключается в том, что почти любой разделитель является легальным для маркеров начала и конца, в зависимости от того, что облегчает остальную реализацию. Итак, # foo # является законным,/foo/является законным,! Foo! является законным (я думаю) и т.д. Неопределенное регулярное выражение, я бы сказал, чрезвычайно опасно именно по этой причине. Это звучит как ошибка спецификации HTML5, которая не указана.
Может быть, в PHP, сканировать строку и выбрать разделитель из белого списка, которого нет в строке? (Например, если нет/использовать, если используется #, если там используются% и т.д.)
Я думаю, что chr(0)
будет работать нормально. Изменить: нет. Но chr(1)
работает.
Учитывая, что PHP-приложение (Drupal в этом случае) генерирует поле ввода, кажется, что обходным путем было бы сделать что-то по строкам:
$pattern = '[0-9]/[0-9]';
...
$cleanPattern = preg_replace('/\//', '\\/', $pattern);
preg_match('/' . $cleanPattern . '/', $subject, $matches);
Я не мог придумать случай, когда это не сработает, причем /
используется как литерал в выражении.
Спецификация HTML5 отменяет ECMA262 для спецификации юридического шаблона:
Если указано, значение атрибута должно соответствовать произведению шаблона JavaScript. [ECMA262]
Поскольку существует BNF, определенный в ECMA262, полный парсер (вместо использования PCRE) кажется самым безопасным подходом.