【问题标题】:How can I match everything in a string until the second occurrence of a delimiter with a regular expression?如何匹配字符串中的所有内容,直到第二次出现带有正则表达式的分隔符?
【发布时间】:2011-01-31 13:37:30
【问题描述】:

我正在尝试通过查找第二次出现的句点然后是空格来优化preg_match_all

<?php

$str = "East Winds 20 knots. Gusts to 25 knots. Waters a moderate chop.  Slight chance of showers.";

preg_match_all ('/(^)((.|\n)+?)(\.\s{2})/',$str, $matches);

$dataarray=$matches[2];
foreach ($dataarray as $value)
{ echo $value; }
?>

但它不起作用:{2} 出现不正确。

我必须使用preg_match_all,因为我正在抓取动态 HTML。

我想从字符串中捕获这个:

East Winds 20 knots. Gusts to 25 knots.

【问题讨论】:

    标签: php regex preg-match-all


    【解决方案1】:

    我想从字符串中捕捉到这一点:东风 20 节。阵风至 25 节。

    我有两个建议:

    1) 简单地在“.”(双空格)处分解字符串并打印结果。

    $arr = explode(".  ",$str);
    echo $arr[0] . ".";
    // Output: East Winds 20 knots. Gusts to 25 knots.
    

    2) 使用比 Preg_match_all 对性能更友好的 Explode 和 Strpos。

    foreach( explode(".",$str) as $key=>$val) {
        echo (strpos($val,"knots")>0) ? trim($val) . ". " : "";
    }
    // Output: East Winds 20 knots. Gusts to 25 knots.
    

    【讨论】:

      【解决方案2】:

      为什么不只获取所有句点,然后是一个空格,只使用部分结果?

      preg_match_all('!\. !', $str, $matches);
      echo $matches[0][1]; // second match
      

      不过,我不确定您想从中获取什么。你的问题有点含糊。

      现在,如果您想捕获直到并包括第二个句点(后跟一个空格)的所有内容,请尝试:

      preg_match_all('!^((?:.*?\. ){2})!s', $str, $matches);
      

      它使用非贪婪通配符匹配,DOTALL 所以. 匹配换行符。

      如果您不想捕获最后一个空格,您也可以这样做:

      preg_match_all('!^((?:.*?\.(?= )){2})!s', $str, $matches);
      

      您还可能希望允许字符串终止计数,这意味着:

      preg_match_all('!^((?:.*?\.(?: |\z)){2})!s', $str, $matches);
      

      preg_match_all('!^((?:.*?\.(?= |\z)){2})!s', $str, $matches);
      

      最后,由于您正在完成一场比赛并想要第一场比赛,因此您可以轻松地使用preg_match() 而不是preg_match_all()

      【讨论】:

      • 谢谢,亚历克斯。我正在抓取一个动态列表,但这看起来会起作用: (^)((.|\n)+?)((?:.*?\. ){2}) 你能为我翻译最后一部分吗? ((?:.*?\. ){2}) 第二次出现......嗯?谢谢。
      • @Steve (?:...) 是一个非捕获组,这意味着它不会在$matches 数组中创建单独的条目。否则,它在优先级等方面充当捕获组。.*? 是一个 非贪婪 通配符匹配。通常,正则表达式中的通配符匹配会抓取尽可能多的字符。非贪婪匹配尽可能少地抓取。
      • 好吧,我的简化示例没有让我第二次出现“.”,所以我会告诉你我在做什么:查看来源:weather.noaa.gov/cgi- bin/... 我正在运行: preg_match_all ('/(#800000">)((.|\n)+?)((?:.*?\.\s){2})/',$content,$预测); $dataarray=$forecast[2]; foreach ($dataarray as $value) { echo $value; } 仅尝试获取:今晚南风 10 到 14 节。海湾水域 A Light Chop。星期五西南风 10 To 15 Knots. Bay Waters A Light Chop。仍然没有快乐。有什么想法吗???非常感谢您的帮助...
      【解决方案3】:

      不需要正则表达式。想的简单

      $str = "East Winds 20 knots. Gusts to 25 knots. Waters a moderate chop.  Slight chance of showers.";
      $s = explode(". ",$str);
      $s = implode(". ",array_slice($s,0,2)) ;
      print_r($s);
      

      【讨论】:

        【解决方案4】:

        你可以试试:

        <?php
        $str = "East Winds 20 knots. Gusts to 25 knots. Waters a moderate chop.  Slight chance of showers.";
        if(preg_match_all ('/(.*?\. .*?\. )/',$str, $matches))
            $dataarrray = $matches[1];
        var_dump($dataarrray);
        ?>
        

        输出:

        array(1) {
          [0]=>
          string(40) "East Winds 20 knots. Gusts to 25 knots. "
        }
        

        此外,如果您只想捕获一次事件,为什么要使用 preg_match_allpreg_match 应该足够了。

        【讨论】:

        • 数组中有 3 个 r 的任何原因? :P
        • @alex: 这是对 PHP 解释器的优化提示;)
        【解决方案5】:

        这是一种不同的方法

        $str = "East Winds 20 knots. Gusts to 25 knots. Waters a moderate chop.  Slight chance of showers.";
        
        
        $sentences = preg_split('/\.\s/', $str);
        
        $firstTwoSentences = $sentences[0] . '. ' . $sentences[1] . '.';
        
        
        echo $firstTwoSentences; // East Winds 20 knots. Gusts to 25 knots.
        

        【讨论】:

          【解决方案6】:

          我不认为 (.\s{2}) 意味着你认为它的意思。就目前而言,它将匹配“.”(句点后跟两个空格),而不是“.”的第二次出现

          【讨论】:

          • 谢谢,罗伯。我知道 {2} 是错误的。我认为可能有一个快速修复,所以我简化了我的问题。真实的例子是抓取weather.noaa.gov/cgi-bin/fmtbltn.pl?file=forecasts/marine/… 的来源并执行 preg_match_all 以仅结束:今天东南风 7 到 12 节变成 10 到 13 节。海湾水域中等排骨。今晚东南风 8 到 12 节变为南风 5 到 10 节。海湾水域清淡。等等,每天。有没有办法以现在的结构方式第二次出现“。”?
          猜你喜欢
          • 1970-01-01
          • 2019-09-26
          • 2014-10-19
          • 2011-09-26
          • 1970-01-01
          • 2011-05-19
          • 2020-03-16
          • 2017-09-02
          • 1970-01-01
          相关资源
          最近更新 更多