分隔符不能是字母数字或反斜杠,preg_match

111

我有这段代码:

$string1 = "My name is 'Kate' and im fine"; 
$pattern = "My name is '(.*)' and im fine"; 
preg_match($pattern , $string1, $matches);
echo $matches[1];

当我运行它时,会返回以下错误:

警告:preg_match() [function.preg-match]:定界符不能是字母数字或反斜杠


3
作为可能对他人有帮助的提示,如果您将所有参数作为变量传递给 preg_match() 函数,请确保在函数调用中不要意外混淆变量的顺序,否则几乎肯定会导致出现相同的错误。 - bluebinary
1
你的正则表达式字符串需要一个分隔符。 - Mouradif
2
使用 $pattern = "/我的名字是'(.*)',我很好/"; - gk.
7个回答

160

你的模式需要加上分隔符。它应该在模式的开头和结尾添加,如下所示:

$pattern = "/My name is '(.*)' and im fine/";  // With / as a delimeter 

3
当使用正则表达式时,要小心使用双引号将其括起来,否则某些字符组合(例如 \l 表示换行符)将被转换为其对应的字符,这可能会导致意料之外的表达式。建议使用单引号。详见PHP字符串描述 - Patanjali
在这个例子中,字符串包含单引号,因此更容易使用双引号将其括起来(避免需要转义 \' 如果它被包含在单引号中)。 - Paul
1
我只是做了一个普遍性的评论,因为观看示例的人可能会将它们视为自己“切割饼干”的东西,而没有意识到如果他们将其扩展到其他情况下可能会发生的不可预见的后果。不幸的是,我无法更改我的评论以使其更加具体。 - Patanjali

86

解决方案(其他答案没有提到—至少在我最初编写本文时没有提到)是,当PHP引用定界符时,它不是指你在代码中看到的定界符(这些是引号),而是字符串内部的下一个字符。(事实上,我从未在任何文档中看到过这种说法:你必须在示例中看到它。)所以,与您可能习惯于从许多其他语言中使用的正则表达式语法不同:

/something/

PHP使用字符串,然后在字符串中查找另一个分隔符:

'/something/'

PHP所指的分隔符是一对/字符,而不是一对'字符。因此,如果您编写'something',PHP将把s视为预定的分隔符,并抱怨您不允许使用字母数字字符作为分隔符。

因此,如果您想传递(例如)一个i来显示您想要进行不区分大小写的匹配,可以将其传递到字符串内部但在正则表达式分隔符之外:

'/something/i'

如果你想使用除了/之外的其他分隔符,那么你可以这样做,比如当你匹配一个URL而不想转义所有斜杠时:

如果您想使用其他分隔符,而不是/,比如您要匹配一个URL,但不想转义所有的斜杠:

'~something~'

1
@Gruber:谢谢!你可以随时将链接发送给所有朋友,让他们点赞它 ;) - iconoclast
1
解释文档没有说明的内容。+1 谢谢! - Ju Oliveira
最高得票的答案与此相同,但我很感激现在明白了为什么这是正确的答案。+1 谢谢! - Eclectic

24

您必须为表达式指定分隔符。分隔符是一个特殊字符,用于表示表达式的开始和结束位置,以便您可以使用修饰符和解释器来确定哪部分是表达式,哪些是修饰符。正如错误信息所述,分隔符不能是反斜杠,因为反斜杠是转义字符。

$pattern = "/My name is '(.*)' and im fine/";

下面是相同的示例,但使用 i 修改器进行匹配而不区分大小写。

$pattern = "/My name is '(.*)' and im fine/i";

正如你所看到的,i在斜杠之外,因此被解释为一个修饰符。

还要记住,如果你使用斜杠字符(/)作为定界符,则必须转义正则表达式中出现的其他斜杠。


8

这个模式必须有分隔符。分隔符可以是正斜杠 (/),也可以是任何非字母数字字符(#,$,*,...)。例子:

$pattern = "/My name is '(.*)' and im fine/"; 
$pattern = "#My name is '(.*)' and im fine#";
$pattern = "@My name is '(.*)' and im fine@";  

1
也许与原始代码示例无关,但是我收到了错误消息“分隔符不能是字母数字或反斜杠”,并在这里进行了谷歌搜索。 原因:我混淆了preg_match的参数顺序。模式是第二个参数,要匹配的字符串是第一个参数。请小心 :)

0

你也可以使用 T-Regx 库 ,它为您提供 自动定界符

$matches = pattern("My name is '(.*)' and im fine")->match($string1)->all();

                 // ↑ No delimiters needed 

-2
请尝试使用这个。
 $pattern = "/My name is '\(.*\)' and im fine/"; 

为什么要转义括号? - Mouradif
1
在这个问题中,OP想要提取名称,因此需要使用括号进行匹配,因此不应该转义。这就是为什么我要给它点踩的原因。 - Patanjali

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接