use*_*995 43 php regex wordpress preg-replace
我有以下错误:
警告:preg_replace():第38行的xxx.php中的未知修饰符']'
这是第38行的代码:
<?php echo str_replace("</ul></div>", "", preg_replace("<div[^>]*><ul[^>]*>", "", wp_nav_menu(array('theme_location' => 'nav', 'echo' => false)) )); ?>
Run Code Online (Sandbox Code Playgroud)
有人可以帮我解决这个问题吗?
Ama*_*ali 91
在PHP中,正则表达式需要包含在一对分隔符中.分隔符可以是任何非字母数字,非反斜杠,非空白字符; /
,#
,~
是最常用的.需要注意的是,还可以使用支架风格分隔符在打开和关闭括号开始和结束的分隔符,即<pattern_goes_here>
,[pattern_goes_here]
等等都是有效的.
" 未知修饰符X "错误通常发生在以下两种情况中:
当您的正则表达式缺少分隔符时.
在模式中使用分隔符而不转义它时.
在这种情况下,正则表达式是<div[^>]*><ul[^>]*>
.正则表达式引擎从认为一切<
来>
的正则表达式模式,以及后来的一切作为修饰.
Regex: <div[^> ]*><ul[^>]*>
? ? ? ?
??????? ????????????
pattern modifiers
Run Code Online (Sandbox Code Playgroud)
]
这是一个未知的修饰符,因为它出现在结束>
分隔符之后.这就是PHP抛出该错误的原因.
根据不同的模式,未知的修饰投诉可能也已经约*
,+
,p
,/
或)
或几乎任何其他字母/符号.只有imsxeADSUXJu
在有效PCRE修饰符.
修复很容易.只需使用任何有效的分隔符包装您的正则表达式模式.在这种情况下,您可以选择~并获取以下内容:
~<div[^>]*><ul[^>]*>~
? ?
? ?? ending delimiter
?????????????????????? starting delimiter
Run Code Online (Sandbox Code Playgroud)
如果您在使用分隔符时收到此错误,则可能是因为模式本身包含所述分隔符的未转义的出现.
/foo[^/]+bar/i
肯定会抛出错误.因此,\如果它出现在正则表达式中的任何位置,您可以使用反斜杠转义它:
/foo[^\/]+bar/i
? ? ?
??????????????? actual delimiters
???????? escaped slash(/) character
Run Code Online (Sandbox Code Playgroud)
如果您的正则表达式模式包含如此多的分隔符字符,则这是一项繁琐的工作.
当然,更简洁的方法是使用不同的分隔符.理想情况下,一个字符不会出现在正则表达式模式中的任何位置,比如说#
- #foo[^/]+bar#i
.
preg_quote()
)mar*_*rio 14
该参考答案已经解释了"未知的修饰词"警告的原因.这只是其他典型变体的比较.
忘记添加正则表达式/
分隔符时/
,将假定第一个非字母符号为1.因此,警告常常是关于什么如下分组(…)
,[…]
元符号:
preg_match("[a-zA-Z]+:\s*.$"
? ??
Run Code Online (Sandbox Code Playgroud)有时你的正则表达式已经使用了自定义分隔符(:
这里),但仍然包含与未转义的文字相同的字符.它被误认为是过早的分隔符.这就是下一个符号收到"未知修饰符❌"奖杯的原因:
preg_match(":\[[\d:/]+\]:"
? ? ?
Run Code Online (Sandbox Code Playgroud)使用经典/
分隔符时,请注意不要在正则表达式中使用它.在尝试匹配未转义的文件名时最常发生这种情况:
preg_match("/pathname/filename/i"
? ? ?
Run Code Online (Sandbox Code Playgroud)
或者在匹配角度/方括号样式标签时:
preg_match("/<%tmpl:id>(.*)</%tmpl:id>/Ui"
? ? ?
Run Code Online (Sandbox Code Playgroud)模板式(Smarty或BBCode)正则表达式模式通常需要{…}
或[…]
括号.两者都应该被逃脱.({}
尽管最外面的一对是例外).
当没有使用实际分隔符时,它们也会被误解为配对分隔符.如果他们当时也被用作文字字符,那么那当然是......一个错误.
preg_match("{bold[^}]+}"
? ? ?
Run Code Online (Sandbox Code Playgroud)每当警告说" 分隔符不能是字母数字或反斜杠 "时,你也完全忘记了分隔符:
preg_match("ab?c*"
?
Run Code Online (Sandbox Code Playgroud)" Unkown modifier'g' "通常表示从JavaScript或Perl中逐字复制的正则表达式.
preg_match("/abc+/g"
?
Run Code Online (Sandbox Code Playgroud)
PHP不使用/g
全局标志.相反,该preg_replace
函数适用于所有出现,并且preg_match_all
是一次出现的"全局"搜索附件preg_match
.
所以,只需删除/g
标志.
另请参阅:
· 警告:preg_replace():未知修饰符'g'
· preg_replace:bad regex =='未知修饰符'?
一个更特殊的情况是PCRE_EXTENDED /x
标志.这通常(或应该)用于使regexp更加高尚和可读.
这允许使用内联#
注释.PHP在PCRE上实现了正则表达式分隔符.但它并没有#
以任何特殊方式对待.#
注释中的文字分隔符可能会成为错误:
preg_match("/
ab?c+ # Comment with / slash in between
/x"
Run Code Online (Sandbox Code Playgroud)
(另外值得注意的是,使用#
as #abc+#x
分隔符可能是不可取的.)
将变量插入到正则表达式中需要对它们进行预转义,或者将它们作为有效的正则表达式.你不能事先告诉它是否会起作用:
preg_match("/id=$var;/"
? ? ?
Run Code Online (Sandbox Code Playgroud)
$var = preg_quote($var, "/")
在这种情况下最好适用.
另请参阅:
· ......中的未知修饰符'/'?它是什么?
另一种方法是使用\Q…\E
转义为不带引号的文字字符串:
preg_match("/id=\Q{$var}\E;/mix");
Run Code Online (Sandbox Code Playgroud)
请注意,这仅仅是元符号的便捷快捷方式,不可靠/安全.如果$var
包含文字'\E'
本身(无论多么不可能),它就会崩溃.它并不能掩盖分隔符本身.
不推荐使用的修饰符/ e是一个完全不同的问题.这与分隔符无关,但隐式表达式解释模式正在逐步淘汰.另请参阅: 使用preg_replace_callback替换已弃用的preg_replace/e
如前所述,这个错误的最快解决方案就是选择一个明确的分隔符.可以使用任何非字母符号.视觉上与众不同通常是首选的:
~abc+~
!abc+!
@abc+@
#abc+#
=abc+=
%abc+%
从技术上讲,你可以使用$abc$
或|abc|
用于分隔符.但是,最好避免使用充当正则表达式元字符的符号.
散列#
作为分隔符也很受欢迎.但应注意与x
/ PCRE_EXTENDED
readability修饰符结合使用.你不能使用# inline
或(?#…)
评论,因为那些会被混淆为分隔符.
偶尔你会看到"
并'
使用正则表达式分隔符与它们的conterpart配对作为PHP字符串封装:
preg_match("'abc+'"
preg_match('"abc+"'
Run Code Online (Sandbox Code Playgroud)
就PHP而言,这是完全有效的.它有时方便且不引人注目,但在IDE和编辑器中并不总是清晰可辨.
一个有趣的变体是成对分隔符.您可以使用任何<...>
(...)
[...]
{...}
括号/大括号组合,而不是在正则表达式的两端使用相同的符号.
preg_match("(abc+)" # just delimiters here, not a capture group
Run Code Online (Sandbox Code Playgroud)
虽然它们中的大多数也充当正则表达式元字符,但您可以经常使用它们而无需进一步努力.只要正则表达式中的那些特定括号/ parens正确配对或转义,这些变体就非常易读.
一个有点懒惰的技巧(此处未予以认可)使用不可打印的ASCII字符作为分隔符.通过使用正则表达式字符串的双引号和分隔符的八进制转义,这在PHP中很容易使用:
preg_match("\001 abc+ \001mix"
Run Code Online (Sandbox Code Playgroud)
这\001
只是一个␁通常不需要的控制角色.因此,它几乎不可能出现在大多数正则表达式模式中.这使它适合这里,即使不是很清晰.
遗憾的是,您无法使用Unicode glyps ?
作为分隔符.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;
}
Run Code Online (Sandbox Code Playgroud)正则表达式字符串的其余部分从左到右遍历.仅\\
忽略反斜杠 - 已跳过的符号.\Q
而\E
逃逸没有兑现.
如果再次找到分隔符,则验证余数仅包含修饰符字母.
如果分隔符是([{< )]}> )]}>
可配对的括号/括号之一,则处理逻辑更精细.
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++;
}
Run Code Online (Sandbox Code Playgroud)
它查找正确配对的左右分隔符,但在计数时忽略其他大括号/括号类型.
只有在分隔符和修饰符标志被删除后,才会将原始正则表达式字符串传递给PCRE后端.
现在这有点无关紧要了.但解释了分隔符警告的来源.这整个过程都是至少具有Perl兼容性.当然有一些小的偏差,比如[…]
没有在PHP中接受特殊处理的字符类上下文.
归档时间: |
|
查看次数: |
33031 次 |
最近记录: |