У меня есть следующая ошибка:
Предупреждение: preg_replace (): Неизвестный модификатор ']' в xxx.php в строке 38
Это код в строке 38:
<?php echo str_replace("</ul></div>", "", preg_replace("<div[^>]*><ul[^>]*>", "", wp_nav_menu(array('theme_location' => 'nav', 'echo' => false)) )); ?>
Может кто-то, пожалуйста, помогите мне решить эту проблему?
В PHP регулярное выражение должно быть заключено в пару разделителей . Разделителем может быть любой небуквенный символ, не обратный слэш, не-пробельный символ; /
, #
, ~
являются наиболее часто используемыми. Обратите внимание, что также можно использовать разделители стиля скобок, где открывающие и закрывающие скобки являются начальным и конечным разделителем, т.е. <pattern_goes_here>
, [pattern_goes_here]
и т. Д. Все действуют.
Ошибка « Неизвестный модификатор X » обычно возникает в следующих двух случаях:
Когда в вашем регулярном выражении отсутствуют разделители .
Когда вы используете разделитель внутри шаблона, не избегая его.
В этом случае регулярное выражение <div[^>]*><ul[^>]*>
. Механизм регулярных выражений рассматривает все от <
to >
как шаблон регулярного выражения, а потом все как модификаторы.
Regex: <div[^> ]*><ul[^>]*> │ │ │ │ └──┬──┘ └────┬─────┘ pattern modifiers
]
здесь неизвестный модификатор, потому что он появляется после закрытия >
разделителя. Именно поэтому PHP генерирует эту ошибку.
В зависимости от шаблона, неизвестная жалоба-модификатор также могла быть о *
, +
, p
, /
или )
или почти любой другой букве / символе. Только imsxeADSUXJu
являются действительными модификаторами PCRE .
Исправить легко. Просто оберните шаблон регулярного выражения любыми действительными разделителями. В этом случае вы можете выбрать ~ и получить следующее:
~<div[^>]*><ul[^>]*>~ │ │ │ └─ ending delimiter └───────────────────── starting delimiter
Если вы получаете эту ошибку, несмотря на использование разделителя, возможно, это связано с тем, что сам шаблон содержит несвязанные вхождения указанного разделителя.
/foo[^/]+bar/i
, безусловно, вызовет ошибку. Таким образом, вы можете избежать этого, используя \ backslash, если он появляется в любом месте регулярного выражения:
/foo[^\/]+bar/i │ │ │ └──────┼─────┴─ actual delimiters └─────── escaped slash(/) character
Это утомительная работа, если ваш шаблон регулярного выражения содержит так много вхождений символа разделителя.
Разумеется, более чистым способом было бы использовать другой разделитель. В идеале символ, который не появляется нигде внутри шаблона регулярного выражения, скажем #
– #foo[^/]+bar#i
.
preg_quote()
) Справочный ответ уже объясняет причину предупреждений «Неизвестный модификатор». Это просто сравнение других типичных вариантов.
Когда вы забываете добавлять регулярные выражения /
разделители /
, первый небуквенный символ будет считаться одним. Поэтому предупреждение часто о том, что следует за группировкой (…)
, […]
метасимволом:
preg_match("[a-zA-Z]+:\s*.$" ↑ ↑⬆
Иногда ваше регулярное выражение уже использует пользовательский разделитель ( :
здесь), но по-прежнему содержит тот же символ, что и неэкранированный литерал. Это ошибочно считается преждевременным разделителем. Вот почему следующий символ получает трофей «Неизвестный модификатор»:
preg_match(":\[[\d:/]+\]:" ↑ ⬆ ↑
При использовании классического /
разделителя, будьте осторожны, чтобы не иметь его в регулярном выражении буквально. Это чаще всего происходит при попытке сопоставления имен файлов без имени :
preg_match("/pathname/filename/i" ↑ ⬆ ↑
Или при сопоставлении тегов стиля угла / квадрата:
preg_match("/<%tmpl:id>(.*)</%tmpl:id>/Ui" ↑ ⬆ ↑
Шаблоны регулярных выражений (Smarty или BBCode) часто требуют скобки {…}
или […]
. Оба они обычно должны быть экранированы. (Исключением является внешняя {}
пара).
Они также ошибочно интерпретируются как парные разделители, когда фактический разделитель не используется. Если они тогда также используются как буквальный символ внутри, то это, конечно … ошибка.
preg_match("{bold[^}]+}" ↑ ⬆ ↑
Всякий раз, когда в предупреждении говорится, что « разделитель не должен быть буквенно-цифровым или обратным слэшем », вы также полностью забыли разделители:
preg_match("ab?c*" ↑
« Неизвестный модификатор« g »часто указывает регулярное выражение, которое было скопировано дословно из JavaScript или Perl.
preg_match("/abc+/g" ⬆
PHP не использует глобальный флаг /g
. Вместо этого функция preg_replace
работает во всех вхождениях, а preg_match_all
– это «глобальный» поисковый кулон для одного события preg_match
.
Итак, просто удалите флаг /g
.
Смотрите также:
· Предупреждение: preg_replace (): Неизвестный модификатор 'g'
· Preg_replace: bad regex == 'Неизвестный модификатор'?
Более странный случай относится к значку PCRE_EXTENDED /x
. Это часто (или должно быть) используется для создания более эффективных и читаемых регулярных выражений.
Это позволяет использовать встроенные комментарии #
. PHP реализует разделители регулярных выражений поверх PCRE. Но он не обрабатывает #
каким-либо особым образом. Вот как буквальный разделитель в #
комментарии может стать ошибкой:
preg_match("/ ab?c+ # Comment with / slash in between /x"
(Также следует отметить, что использование #
как #abc+#x
разделителя может быть вдвойне нецелесообразным).
Интерполяция переменных в регулярное выражение требует, чтобы они были предварительно экранированы или были правильными регулярными выражениями. Вы не можете сказать заранее, если это сработает:
preg_match("/id=$var;/" ↑ ↺ ↑
В таких случаях лучше всего применить $var = preg_quote($var, "/")
.
Смотрите также:
· Неизвестный модификатор '/' в …? что это?
Другой альтернативой является использование \Q…\E
экранов для строк без кавычек:
preg_match("/id=\Q{$var}\E;/mix");
Обратите внимание, что это просто удобный ярлык, не надежный / безопасный. Он распался бы, если бы $var
содержал буквальный '\E'
(хотя и маловероятный).
Устаревший модификатор / e – совершенно другая проблема. Это не имеет ничего общего с разделителями, но режим интерпретации неявных выражений постепенно прекращается. См. Также: Заменить устаревшие preg_replace / e с preg_replace_callback
Как уже упоминалось, самое быстрое решение этой ошибки – это просто выбор четкого разделителя. Можно использовать любой символ без буквы. Часто предпочтительны визуально отличительные:
~abc+~
!abc+!
@abc+@
#abc+#
=abc+=
%abc+%
Технически вы можете использовать $abc$
или |abc|
для разделителей. Тем не менее, лучше избегать символов, которые служат метасимволами регулярного выражения.
Хеш #
как разделитель тоже довольно популярен. Но следует соблюдать осторожность в сочетании с модификатором удобочитаемости x
/ PCRE_EXTENDED
. Вы не можете использовать комментарии # inline
или (?#…)
, потому что они будут смущены как разделители.
Иногда вы видите "
и '
используемые в качестве разделителей регулярных выражений в сочетании с их conterpart как оболочкой строки PHP:
preg_match("'abc+'" preg_match('"abc+"'
Что совершенно верно для PHP. Это иногда удобно и ненавязчиво, но не всегда разборчиво в IDE и редакторах.
Интересным вариантом являются парные разделители. Вместо того, чтобы использовать один и тот же символ на обоих концах регулярного выражения, вы можете использовать любую комбинацию <...>
(...)
[...]
{...}
скобок / фигурных скобок.
preg_match("(abc+)" # just delimiters here, not a capture group
Хотя большинство из них также служат метасимволами регулярных выражений, вы можете часто использовать их без дополнительных усилий. Пока эти конкретные фигурные скобки / parens внутри регулярного выражения спарены или экранированы правильно, эти варианты вполне читаемы.
Несколько ленивый трюк (который не поддерживается настоящим) использует непечатаемые символы ASCII в качестве разделителей. Это легко работает в PHP, используя двойные кавычки для строки регулярных выражений и восьмеричные escape-последовательности для разделителей:
preg_match("\001 abc+ \001mix"
\001
– это только контрольный символ ␁, который обычно не требуется. Поэтому он вряд ли появится в большинстве шаблонов регулярных выражений. Это делает его подходящим здесь, хотя и не очень разборчивым.
К сожалению, вы не можете использовать символы Unicode ❚
качестве разделителей. PHP допускает только однобайтовые символы. И почему так? Ну, рад, что вы спросили:
В preg_*
используется механизм регулярного выражения PCRE , который сам по себе не заботится или не предусматривает разделителей. Для сходства с Perl функции preg_*
реализуют их. Именно поэтому вы можете использовать буквы-модификаторы /ism
вместо констант в качестве параметра .
См. Ext / pcre / php_pcre.c о том, как строка регулярных выражений предварительно обрабатывается:
Сначала все ведущие пробелы игнорируются.
В качестве предполагаемого разделителя принимается любой символ, отличный от алфавита. Обратите внимание, что PHP выполняет только однобайтовые символы:
delimiter = *p++; if (isalnum((int)*(unsigned char *)&delimiter) || delimiter == '\\') { php_error_docref(NULL,E_WARNING, "Delimiter must not…"); return NULL; }
Остальная строка регулярного выражения перемещается влево-вправо. Символы с обратной косой чертой игнорируются.
Если разграничитель будет найден снова, остаток проверяется только на букву модификатора.
Если разделитель является одним из ([{< )]}> )]}>
скрытых скобок / скобок, то логика обработки более сложна.
int brackets = 1; /* brackets nesting level */ while (*pp != 0) { if (*pp == '\\' && pp[1] != 0) pp++; else if (*pp == end_delimiter && --brackets <= 0) break; else if (*pp == start_delimiter) brackets++; pp++; }
Он ищет правильно спаренный левый и правый разделитель, но при подсчете игнорирует другие фигурные скобки / типы скобок.
Необработанная строка регулярных выражений передается на сервер PCRE только после того, как флаги-разделители и флаги-модификаторы были вырезаны.
Теперь все это несколько не имеет значения. Но объясняет, откуда берутся предупреждения с разделителями. И вся эта процедура должна иметь минимум совместимости с Perl. Конечно, есть несколько незначительных отклонений, например, контекст класса символа […]
не получающий специального лечения в PHP.