警告:preg_replace():未知修饰符']'
我有以下错误:
警告:第38行的xxx.php中的preg_replace():未知修饰符']'
这是第38行的代码:
<?php echo str_replace("</ul></div>", "", preg_replace("<div[^>]*><ul[^>]*>", "", wp_nav_menu(array('theme_location' => 'nav', 'echo' => false)) )); ?>
有人可以帮我解决这个问题吗?
为什么发生错误
在PHP中,正则expression式需要包含在一对分隔符中 。 分隔符可以是任何非字母数字,非反斜杠,非空白字符; /
, #
, ~
是最常用的。 请注意,也可以使用括号格式分隔符,其中开始和结束括号是开始和结束分隔符,即<pattern_goes_here>
, [pattern_goes_here]
等都是有效的。
“ Unknown modifier X ”错误通常发生在以下两种情况下:
-
当你的正则expression式缺less分隔符 。
-
当您在图案内使用分隔符 而不逃脱它。
在这种情况下,正则expression式是<div[^>]*><ul[^>]*>
。 正则expression式引擎将从<
到>
所有内容视为正则expression式模式,之后将所有内容视为修饰符。
Regex: <div[^> ]*><ul[^>]*> │ │ │ │ └──┬──┘ └────┬─────┘ pattern modifiers
]
这是一个未知的修饰符,因为它在closures>
分隔符后出现。 这就是为什么PHP抛出这个错误。
根据不同的模式,未知的修饰符投诉可能是关于*
, +
, p
, /
或)
或几乎任何其他字母/符号。 只有imsxeADSUXJu
是有效的PCRE修饰符 。
如何解决它
修复很简单。 只要用任何有效的分隔符包装你的正则expression式模式。 在这种情况下,您可以select〜并获得以下内容:
~<div[^>]*><ul[^>]*>~ │ │ │ └─ ending delimiter └───────────────────── starting delimiter
如果尽pipe使用了分隔符,仍然收到此错误,可能是因为该模式本身包含所述分隔符的非转义事件。
或逃生分隔符
/foo[^/]+bar/i
肯定会抛出一个错误。 所以如果它出现在正则expression式中的任何地方,你可以使用\ backslash来转义它:
/foo[^\/]+bar/i │ │ │ └──────┼─────┴─ actual delimiters └─────── escaped slash(/) character
如果你的正则expression式模式中包含了这么多的分隔字符,这是一个单调乏味的工作。
更干净的方法当然是完全使用不同的分隔符。 理想情况下,一个字符不会出现在正则expression式模式中,例如#
– #foo[^/]+bar#i
。
更多阅读:
- PHP的正则expression式分隔符
- http://www.regular-expressions.info/php.html
- 如何将eregexpression式转换为PHP中的preg? (缺less分隔符)
- 未知的修饰符'/'在…? 它是什么? (使用
preg_quote()
)
其他例子
参考答案已经解释了“未知修饰符”警告的原因。 这只是其他典型变体的比较。
-
当忘记添加正则expression式
/
分隔符/
,第一个非字母符号将被假定为一个。 因此,警告常常是关于分组(…)
,元符号后面的内容:preg_match("[a-zA-Z]+:\s*.$" ↑ ↑⬆
-
有时你的正则expression式已经使用了一个自定义分隔符(
:
这里),但仍然包含与未转义文字相同的字符。 这被误认为是过早的分隔符。 这就是为什么下一个符号收到“未知修饰符”奖杯:preg_match(":\[[\d:/]+\]:" ↑ ⬆ ↑
-
使用经典
/
分隔符时,请注意不要在正则expression式中使用它。 尝试匹配未转义的文件名时最常发生这种情况:preg_match("/pathname/filename/i" ↑ ⬆ ↑
或者当匹配angular度/方括号风格的标签 :
preg_match("/<%tmpl:id>(.*)</%tmpl:id>/Ui" ↑ ⬆ ↑
-
模板式(Smarty或BBCode)正则expression式模式通常需要
{…}
或括号。 两者通常应该逃脱。 (最外面的{}
对是例外)。当没有使用实际的分隔符时,它们也被误解为成对的分隔符。 如果他们也被用作文字字符,那当然是一个错误。
preg_match("{bold[^}]+}" ↑ ⬆ ↑
-
每当警告说“ 分隔符不能是字母数字或反斜杠 ”,那么你也完全忘记了分隔符:
preg_match("ab?c*" ↑
-
“ unkown修饰符”g“ ”通常表示从JavaScript或Perl逐字拷贝的正则expression式。
preg_match("/abc+/g" ⬆
PHP不使用
/g
全局标志。 相反,preg_replace
函数适用于所有的事件,preg_match_all
是preg_match_all
的“全局”search。所以,只要删除
/g
标志。也可以看看:
· 警告:preg_replace():未知修饰符“g”
· preg_replace:坏正则expression式=='未知的修饰符'? -
一个更奇怪的情况属于PCRE_EXTENDED
/x
标志 。 这经常(或应该)用于使正则expression式更高明和可读。这允许使用内嵌
#
评论。 PHP在PCRE上实现了正则expression式分隔符。 但它不会以任何特殊的方式处理#
这是如何在#
注释中的文字分隔符可以成为一个错误:preg_match("/ ab?c+ # Comment with / slash in between /x"
(另外值得注意的是,使用
#
as#abc+#x
分隔符可以是不可取的。) -
插入variables到正则expression式需要它们被预先转义,或者是有效的正则expression式本身。 事先不知道这是否会奏效:
preg_match("/id=$var;/" ↑ ↺ ↑
在这种情况下最好应用
$var = preg_quote($var, "/")
。也可以看看:
·…中的未知修饰符“/”? 它是什么?另一种select是使用
\Q…\E
转义为未加引号的文字string:preg_match("/id=\Q{$var}\E;/mix");
请注意,这只是一个方便的捷径,不可靠/安全。 如果
$var
包含一个字面上的'\E'
本身(不太可能),它就会崩溃。 -
弃用的修饰符/ e是一个完全不同的问题。 这与分隔符无关,但隐含的expression式解释模式正在被逐步淘汰。 另请参阅: 用preg_replace_callbackreplace弃用的preg_replace / e
可选的正则expression式分隔符
正如已经提到的,解决这个错误最快的办法就是select一个明确的分隔符。 任何非字母符号都可以使用。 视觉上有特色的往往是首选的:
-
~abc+~
-
!abc+!
-
@abc+@
-
#abc+#
-
=abc+=
-
%abc+%
技术上你可以使用$abc$
或|abc|
为分隔符。 但是,最好避免使用符号作为正则expression式元字符。
散列#
作为分隔符也相当stream行。 但是应该注意与x
/ PCRE_EXTENDED
可读性修饰符结合使用。 您不能使用# inline
或(?#…)
注释,因为这些会被混淆为分隔符。
仅引用分隔符
偶尔你会看到"
和'
作为正则expression式分隔符与它们的conterpart配对作为PHPstringshell:
preg_match("'abc+'" preg_match('"abc+"'
就PHP而言,这是完全有效的。 这有时是方便和不显眼的,但在IDE和编辑中并不总是清晰的。
配对分隔符
一个有趣的变化是配对分隔符。 而不是在正则expression式的两端使用相同的符号,你可以使用任何<...>
(...)
[...]
括号/大括号的组合。
preg_match("(abc+)" # just delimiters here, not a capture group
虽然他们大多数也可以作为正则expression元字符,你可以经常使用他们没有进一步的努力。 只要正则expression式中的那些特定的大括号/ parens正确地配对或转义,这些变体是相当可读的。
花式正则expression式分隔符
一个有点懒惰的技巧(这是不赞成在此)使用不可打印的ASCII字符作为分隔符。 这很容易在PHP中使用正则expression式string的双引号和分隔符的八进制转义:
preg_match("\001 abc+ \001mix"
\001
只是一个控制angular色,通常不需要。 因此,在大多数正则expression式模式中出现的可能性很小。 这使得它适合在这里,即使不是很清楚。
可悲的是,你不能使用Unicode glyps❚作为分隔符。 PHP只允许单字节字符。 为什么是这样? 那么,很高兴你问:
PCRE上的PHP分隔符
preg_*
函数使用PCRE正则expression式引擎,它本身不关心或提供分隔符。 与Perl类似, preg_*
函数实现它们。 这也是为什么你可以使用修饰符字母/ism
而不是常量作为参数 。
请参阅ext / pcre / php_pcre.c关于正则expression式string是如何预处理的:
-
首先,所有领先的空白都被忽略。
-
任何非字母数字符号被视为推定的分隔符。 请注意,PHP只支持单字节字符:
delimiter = *p++; if (isalnum((int)*(unsigned char *)&delimiter) || delimiter == '\\') { php_error_docref(NULL,E_WARNING, "Delimiter must not…"); return NULL; }
-
正则expression式string的其余部分从左到右遍历。 只有反斜杠
\\
转义的符号被忽略。 -
如果再次find分隔符,其余部分将被validation为只包含修饰符字母。
-
如果分隔符是
([{< )]}> )]}>
可配对括号/括号之一,则处理逻辑更加精细。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++; }
它会查找正确配对的左右分隔符,但在计算时会忽略其他大括号/括号types。
-
原始正则expression式string只有在分隔符和修饰符标志被剪切后才传递给PCRE后端。
现在这一切都是不相关的。 但解释了分隔符警告的来源。 而这整个过程都具有最小的Perl兼容性。 当然还有一些小的偏差,比如在PHP中没有受到特殊处理的字符类上下文。
更多参考
- 的preg_match(); – 未知修饰符“+”
- PHP中的未知修饰符“/”错误
- PHP RegExpr错误Unkown修饰符'('
- 使用preg_match()和REGEXexpression式时,未知修饰符'('')
- PHP:正则expression式 – 未知修饰符错误
- 警告:preg_match()[function.preg-match]:未知修饰符'('
- preg_match():什么时候会发生未知的修饰符错误?
(只是一个精心编写的问题,展示了先前的研究)