【问题标题】:PHP preg_match_all regex to extract only number in stringPHP preg_match_all 正则表达式仅提取字符串中的数字
【发布时间】:2012-03-31 02:48:11
【问题描述】:

我似乎无法找出正确的正则表达式来从字符串中提取特定数字。我有一个包含各种 img 标签的 HTML 字符串。 HTML中有一堆img标签,我想从中提取一部分值。它们遵循以下格式:

<img src="http://domain.com/images/59.jpg" class="something" />
<img src="http://domain.com/images/549.jpg" class="something" />
<img src="http://domain.com/images/1249.jpg" class="something" />
<img src="http://domain.com/images/6.jpg" class="something" />

因此,在“通常”是 .jpg(它可能是 .gif、.png 或其他文件)之前的不同长度的数字。我只想从该字符串中提取数字。

第二部分是我想使用该数字在数据库中查找条目并获取该特定图像 ID 的 alt/title 标记。最后,我想将返回的数据库值添加到字符串中,并将其返回到 HTML 字符串中。

任何关于如何进行的想法都会很棒......

到目前为止,我已经尝试过:

$pattern = '/img src="http://domain.com/images/[0-9]+\/.jpg';
preg_match_all($pattern, $body, $matches);
var_dump($matches);

【问题讨论】:

  • 你只需要使用一个捕获组。你试过什么?
  • 用我迄今为止尝试过的内容编辑了帖子

标签: php regex preg-match-all


【解决方案1】:

使用正则表达式,你可以很容易地得到数字。 preg_match_all 的第三个参数是一个引用数组,将填充找到的匹配项。

preg_match_all('/<img src="http:\/\/domain.com\/images\/(\d+)\.[a-zA-Z]+"/', $html, $matches);
print_r($matches);

这将包含它找到的所有东西。

【讨论】:

    【解决方案2】:

    使用preg_match_all:

    preg_match_all('#<img.*?/(\d+)\.#', $str, $m);
    print_r($m);
    

    输出:

    Array
    (
        [0] => Array
            (
                [0] => <img src="http://domain.com/images/59.
                [1] => <img src="http://domain.com/images/549.
                [2] => <img src="http://domain.com/images/1249.
                [3] => <img src="http://domain.com/images/6.
            )
    
        [1] => Array
            (
                [0] => 59
                [1] => 549
                [2] => 1249
                [3] => 6
            )
    
    )
    

    【讨论】:

    • 捕获字符串中的每个数字,而不仅仅是标签
    【解决方案3】:

    这个正则表达式应该匹配数字部分:

    \/images\/(?P<digits>[0-9]+)\.[a-z]+
    

    你的$matches['digits'] 应该有你想要的所有数字作为一个数组。

    【讨论】:

      【解决方案4】:
      $matches = array();
      preg_match_all('/[:digits:]+/', $htmlString, $matches);
      

      然后循环遍历matches 数组以重建 HTML 并在数据库中查找。

      【讨论】:

        【解决方案5】:

        考虑使用preg_replace_callback

        使用这个正则表达式:(images/([0-9]+)[^"]+")

        然后,作为callback 参数,使用匿名函数。结果:

        $output = preg_replace_callback(
            "(images/([0-9]+)[^\"]+\")",
            function($m) {
                // $m[1] is the number.
                $t = getTitleFromDatabase($m[1]); // do whatever you have to do to get the title
                return $m[0]." title=\"".$t."\"";
            },
            $input
        );
        

        【讨论】:

          【解决方案6】:

          我认为这是最好的方法:

          1. 使用 HTML 解析器提取图像标签
          2. 使用正则表达式(或者可能是字符串操作)来提取 ID
          3. 数据查询
          4. 使用 HTML 解析器插入返回的数据

          这是一个例子。我能想到一些改进,例如使用字符串操作而不是正则表达式。

          $html = '<img src="http://domain.com/images/59.jpg" class="something" />
          <img src="http://domain.com/images/549.jpg" class="something" />
          <img src="http://domain.com/images/1249.jpg" class="something" />
          <img src="http://domain.com/images/6.jpg" class="something" />';
          $doc = new DOMDocument;
          $doc->loadHtml( $html);
          
          foreach( $doc->getElementsByTagName('img') as $img)
          {
              $src = $img->getAttribute('src');
              preg_match( '#/images/([0-9]+)\.#i', $src, $matches);
              $id = $matches[1];
              echo 'Fetching info for image ID ' . $id . "\n";
          
              // Query stuff here
              $result = 'Got this from the DB';
          
              $img->setAttribute( 'title', $result);
              $img->setAttribute( 'alt', $result);
          }
          
          $newHTML = $doc->saveHtml();
          

          【讨论】:

          • 我喜欢这种方法,但我应该如何处理格式错误的 HTML 的警告(img 标签是带有尾随 /> 的 XHTML 大杂烩)。
          • HTML 解析器应该可以很好地处理格式错误的 HTML - 您能否在原始帖子中发布一些错误示例?
          • 弄明白了——这只是一个警告,但它解析正确,所以我只是在 loadHTML 行前面扔了一个@。不过,另一个问题是,我可以只保存部分 HTML,而不是创建要保存的整个 HTML 文档吗?我正在搜索的字符串不是整个文档,而只是包含在

            标记中的一部分。

          • @jpea:参见libxml_use_internal_errors,是的,loadHTML 也可以很好地处理 HTML 块。否则:sprintf("&lt;body&gt;%s&lt;/body&gt;", $htmlChunk); - 但我认为在你的情况下这不是必需的。另见my answer which is similar but differently
          【解决方案7】:

          在解析糟糕的 HTML 时,单独的正则表达式有点失败。 DOMDocument 的 HTML 处理非常好,可以提供新鲜的 tagoup,xpath 来选择你的图像 srcs 和一个简单的 sscanf 来提取数字:

          $ids = array();
          $doc = new DOMDocument();
          $doc->loadHTML($html);
          foreach(simplexml_import_dom($doc)->xpath('//img/@src[contains(., "/images/")]') as $src) {
              if (sscanf($src, '%*[^0-9]%d', $number)) {
                  $ids[] = $number;
              }
          }
          

          因为只给你一个数组,为什么不封装呢?

          $html = '<img src="http://domain.com/images/59.jpg" class="something" />
          <img src="http://domain.com/images/549.jpg" class="something" />
          <img src="http://domain.com/images/1249.jpg" class="something" />
          <img src="http://domain.com/images/6.jpg" class="something" />';
          
          $imageNumbers = new ImageNumbers($html);
          
          var_dump((array) $imageNumbers);
          

          这给了你:

          array(4) {
            [0]=>
            int(59)
            [1]=>
            int(549)
            [2]=>
            int(1249)
            [3]=>
            int(6)
          }
          

          通过上面的那个函数很好地包装成ArrayObject

          class ImageNumbers extends ArrayObject
          {
              public function __construct($html) {
                  parent::__construct($this->extractFromHTML($html));
              }
              private function extractFromHTML($html) {
                  $numbers = array();
                  $doc = new DOMDocument();
                  $preserve = libxml_use_internal_errors(TRUE);
                  $doc->loadHTML($html);
                  foreach(simplexml_import_dom($doc)->xpath('//img/@src[contains(., "/images/")]') as $src) {
                      if (sscanf($src, '%*[^0-9]%d', $number)) {
                          $numbers[] = $number;
                      }
                  }
                  libxml_use_internal_errors($preserve);
                  return $numbers;
              }
          }
          

          如果您的 HTML 格式错误,甚至 DOMDocument::loadHTML() 都无法处理,那么您只需在 ImageNumbers 类内部处理即可。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2011-12-05
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2011-05-10
            • 2014-08-25
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多