【问题标题】:Function preg_match() returns nothing函数 preg_match() 不返回任何内容
【发布时间】:2013-07-24 09:57:31
【问题描述】:

我想在我的代码中使用preg_match(),但结果什么都没有……(或者 null 或空?)

$domain = "stackoverflow.com";

$uriToTest = "http://stackoverflow.com/";

$pattern = "/^http(s)?://(([a-z]+)\.)*".$domain."/";

echo preg_match($pattern, $uriToTest);

有什么问题?

【问题讨论】:

  • 我认为你有错误,是吗?
  • 您遇到了一个错误 - 您需要转义正斜杠。 preg_match 返回错误
  • 您还需要转义 .在 .com 中。
  • 您的模式无效。所以它应该显示错误。检查您的错误日志。检查你的模式。你想要什么。
  • 此外,如果您希望 $domain 与字面匹配,您应该使用 preg_quote() 并交出您使用的正则表达式分隔符。否则正则表达式特殊字符(如字符串中的 .)可能会匹配您意想不到的内容。

标签: php regex preg-match


【解决方案1】:

如果你看看你的模式,就是这个

/^http(s)?://(([a-z]+)\.)*stackoverflow.com/

分隔符用作匹配字符,如果您打开了错误,您会收到"Unknown modifier" 错误。所以第一个提示:TURN ERROR REPORTING ON!

要修复它,请尝试使用不同的分隔符,例如{},因为它比 leaning toothpicks 的负载更容易阅读...

{^http(s)?://(([a-z]+)\.)*stackoverflow.com}

另一个问题是$domain 中的点成为通配符匹配 - 每当您将未知数据插入正则表达式时,请养成使用 preg_quote 转义它的习惯,例如

$pattern = "{^http(s)?://(([a-z]+)\.)*" . preg_quote($domain, '{') . "}";

(注意 - 来自 cmets 中的 stema 的好消息:如果您使用不同的分隔符,则必须传递该 preg_quote。它足够聪明地发现成对的分隔符,因此如果您传递 {,它也会转义 }。 )

【讨论】:

  • +1 将preg_quote($domain) 添加到您的答案中。但是您不应该将分隔符添加为参数,例如preg_quote($string, '/')吗?但我不知道如何添加它,如果你使用一对括号作为分隔符。
  • 这是一个非常好的观点 - 我检查过,如果你通过 '{' 它也会转义 '}'。我会修改的。
  • 我明白我现在的问题是什么。我试过 { } 但我不知道 preg_quote ... - 为什么当我在末尾添加斜杠时,它不起作用?像这样: "{^http(s)?://(([a-z]+)\.)*".preg_quote($domain, '{')."/}" (我想抓住这个以避免域像stackoverflow.com.eu ...)对不起我的愚蠢问题...但是PHP中的正则表达式不是我的朋友^^
  • 哦...好吧,可能是我的 $domain 出错了... :) - 感谢您的帮助!
【解决方案2】:

您很可能遇到错误,preg_match 返回 false,因为您没有转义表达式中的正斜杠。要么使用 # 之类的其他东西作为表达式分隔符,要么转义任何正斜杠以阻止解析器尝试结束表达式(/ 应该是 \/ - 或者将任一端的 / 更改为 @ 987654326@)

//Quick fix to yours
$pattern = "/^http(s)?:\/\/(([a-z]+)\.)*".preg_quote($domain,'/')."/";
//More legible fix
$pattern = '#^https?://(([a-z]+)\.)*'.preg_quote($domain,'#').'#';

请注意,https 中的 s 不需要括号(除非您希望捕获它)

【讨论】:

    【解决方案3】:

    你需要转义你的正斜杠和域名中的.

    $domain = "stackoverflow.com";
    
    $uriToTest = "http://stackoverflow.com/";
    
    $escapedDomain = str_replace('.', '\.', $domain);
    
    $pattern = "/^http(s)?:\/\/(([a-z]+)\.)*".$escapedDomain."/";
    
    echo preg_match($pattern, $uriToTest);
    

    【讨论】:

      【解决方案4】:
        $domain = "stackoverflow.com";
      
        $uriToTest = "http://stackoverflow.com/";
      
        $pattern = "^http(s)?://(([a-z]+)\.)*" . $domain . "^";
      
        preg_match($pattern, $uriToTest, $matches);
        print_r($matches);
      

      【讨论】:

      • 你为什么使用字符串锚^的开头作为正则表达式分隔符?
      • 为了避免出错。 preg_match 分隔符必须从反斜杠开始。你也可以这样写 $pattern = "^\http(s)?://(([a-z]+)\.)*".$domain."^";
      • 我同意,我认为这是令人困惑的建议
      • 但是你引入了另一个错误。 OP 已经在正则表达式中使用了正则表达式特殊字符 ^ 来匹配字符串的开头。
      【解决方案5】:

      如果你使用T-Regx,那么会立即抛出这个异常:

      $domain = "stackoverflow.com";
      $uriToTest = "http://stackoverflow.com/";
      
      try
      {
          pattern("/^http(s)?://(([a-z]+)\.)*" . $domain . '/')->match($uriToTest);
      }
      catch (SafeRegexException $e) {
          echo $e->getMessage();    // `Unknown modifier '/'`
      }
      

      还有!! T-Regx 可以自动添加分隔符,所以你可以去

      pattern("^http(s)?://(([a-z]+)\.)*" . $domain)->match($uriToTest);
      

      它会自动为您添加合适的分隔符。

      【讨论】:

        猜你喜欢
        • 2018-08-27
        • 1970-01-01
        • 1970-01-01
        • 2021-12-22
        • 2017-06-23
        • 2016-08-10
        • 2022-01-12
        • 2020-01-10
        • 2021-07-23
        相关资源
        最近更新 更多