PHP笔记(一):如何利用正则匹配图片路径

这几天一直在百度知道转悠,尝试着解决自己能够解决的问题,从而达到助人为乐的乐趣。(窃笑一下,实际是通过回答别人的问题,达到提升自己的目的;)
转悠了一会,发现有好多朋友提问“PHP怎么读取内容内的图片?”诸如此类的问题。

大多数情况,都是推荐使用正则表达式;不过正则表达式对于我来讲真的不是太懂,曾经有花时间了解过每个字符的作用和使用方法,可长时间不用,早就忘得一干二净了。

面对这样的问题,不能盲目回答,误人子弟的后果很严重啊。。。。查查资料吧

什么是正则表达式?

正则表达式定义

正则表达式(regular expression)描述了一种字符串匹配的模式,可以用来检查一个串是否含有某种子串、将匹配的子串做替换或者从某个串中取出符合某个条件的子串等。

特别字符的使用说明

特别字符 	说明
$ 	匹配输入字符串的结尾位置。如果设置了 RegExp 对象的 Multiline 属性,则 $ 也匹配 'n' 或 'r'。要匹配 $ 字符本身,请使用 $。
( ) 	标记一个子表达式的开始和结束位置。子表达式可以获取供以后使用。要匹配这些字符,请使用 ( 和 )。

* 	匹配前面的子表达式零次或多次。要匹配 * 字符,请使用 *。

+ 	匹配前面的子表达式一次或多次。要匹配 + 字符,请使用 +。

. 	匹配除换行符 n之外的任何单字符。要匹配 .,请使用 。

[ 	标记一个中括号表达式的开始。要匹配 [,请使用 [。

? 	匹配前面的子表达式零次或一次,或指明一个非贪婪限定符。要匹配 ? 字符,请使用 ?。

 	将下一个字符标记为或特殊字符、或原义字符、或向后引用、或八进制转义符。例如, 'n' 匹配字符 'n'。'n' 匹配换行符。序列 '' 匹配 "",而 '(' 则匹配 "("。

^ 	匹配输入字符串的开始位置,除非在方括号表达式中使用,此时它表示不接受该字符集合。要匹配 ^ 字符本身,请使用 ^。

{ 	标记限定符表达式的开始。要匹配 {,请使用 {。

| 	指明两项之间的一个选择。要匹配 |,请使用 |。
构造正则表达式的方法和创建数学表达式的方法一样。也就是用多种元字符与操作符将小的表达式结合在一起来创建更大的表达式。正则表达式的组件可以是单个的字符、字符集合、字符范围、字符间的选择或者所有这些组件的任意组合。

执行选项说明

了解了常见的一些特别字符的含义和正则表达式的构造方法后,再来看看表达式中 /i、/s、/is、/isU等代表着什么意思:

i - 匹配大小写

s - 模式中的圆点元字符(.)匹配所有的字符,包括换行符

x - 模式中的空白字符除了被转义的或在字符类中的以外完全被忽略,在未转义的字符类之外的 # 以及下一个换行符之间的所有字符,包括两 头,也都被忽略

A (PCRE_ANCHORED) - 如果设定了此修正符,模式被强制为“anchored”,即强制仅从目标字符串的开头开始匹配即自动在模式开头加上^。

D (PCRE_DOLLAR_ENDONLY) - 如果设定了此修正符,模式中的美元元字符仅匹配目标字符串的结尾。没有此选项时,如果最后一个字符是换行符的话,美元符号也会匹配此字符之前(但不会匹配 任何其它换行符之前)。如果设定了 m 修正符则忽略此选项。Perl 中没有与其等价的修正符。  S 当一个模式将被使用若干次时,为加速匹配起见值得先对其进行分析。如果设定了此修正符则会进行额外的分析。目前,分析一个模式仅对没有单一固定起始字符的 non-anchored 模式有用。 

U (PCRE_UNGREEDY) - 本修正符反转了匹配数量的值使其不是默认的重复,而变成在后面跟上“?”才变得重复。这和 Perl 不兼容。也可以通过在模式之中设定 (?U) 修正符来启用此选项。

X (PCRE_EXTRA) - 此 修正符启用了一个 PCRE 中与 Perl 不兼容的额外功能。模式中的任何反斜线后面跟上一个没有特殊意义的字母导致一个错误,从而保留此组合以备将 来扩充。默认情况下,和 Perl 一样,一个反斜线后面跟一个没有特殊意义的字母被当成该字母本身。当前没有其它特性受此修正符控制。即:贪婪模式,最 大限度匹配 如:/a[w]+?e/U匹配abceadeddd中的abceade而不是abce,如果不加U修正,则匹配abce  u (PCRE_UTF8) 此修正符启用了一个 PCRE 中与 Perl 不兼容的额外功能。模式字符串被当成 UTF-8。本修正符在 Unix 下自 PHP 4.1.0 起可用,在 win32 下自 PHP 4.2.3 起可用。

认识PHP的PREG_MATCH_ALL函数

PREG_MATCH_ALL的说明

有了以上关于正则表达式的基础知识回顾后,我们再来看看PREG_MATCH_ALL这个函数的基本知识:

preg_match_all -- 进行全局正则表达式匹配
说明 :
int preg_match_all ( string $pattern , string $subject , array &$matches [, int $flags = PREG_PATTERN_ORDER [, int $offset = 0 ]] )

搜索subject中所有匹配pattern给定正则表达式 的匹配结果并且将它们以flag指定顺序输出到matches中.

自第一个匹配找到后, 子序列继续从最后一次匹配位置搜索.

参数:
pattern
    要搜索的模式, 字符串形式.

subject
    输入字符串.

matches
    多维数组, 作为输出参数输出所有匹配结果, 数组排序通过flags指定.

flags
    可以结合下面标记使用(注意不能同时使用PREG_PATTERN_ORDER和 PREG_SET_ORDER):

    PREG_PATTERN_ORDER

        *结果排序为$matches[0]保存完整模式的所有匹配, $matches[1] 保存第一个子组的所有匹配, 以此类推.

PREG_MATCH_ALL的示例

        <?php
        preg_match_all("|<[^>]+>(.*)</[^>]+>|U",
            "<b>example: </b><div align=left>this is a test</div>",
            $out, PREG_PATTERN_ORDER);
        echo $out[0][0] . ", " . $out[0][1] . "n";
        echo $out[1][0] . ", " . $out[1][1] . "n";
        ?>

        以上例程会输出:

        <b>example: </b>, <div align=left>this is a test</div>
        example: , this is a test

        因此, $out[0]是包含匹配完整模式的字符串的数组, $out[1]是包含闭合标签内的字符串的数组.

嗯。差不多知道些正则匹配的道道了。

执行图片路径匹配

问题描述

接下来我们就用PREG_MATCH_ALL来试试手吧。

Q:如何获取下面一段文本内的图片路径?

<img src="http://img.baidu.com/img/logo-zhidao.gif" />
<a href="http://img.baidu.com/img/logo-zhidao.gif">查看百度知道LOGO</a>

解决方法

A:利用PREG_MATCH_ALL,具体代码如下:

$response = '<img src="http://img.baidu.com/img/logo-zhidao.gif" />'
            .'<a href="http://img.baidu.com/img/logo-zhidao.gif">查看百度知道LOGO</a>';
preg_match_all("/(href|src)=(["|']?)([^"'>]+.(jpg|JPG|jpe|JPE|jpeg|JPEG|gif|GIF|png|PNG))/i",$response,$matches);
var_dump($matches);

执行后的结果为:

array(5) {
  [0] => array(2) {
    [0] => string(45) "src="http://img.baidu.com/img/logo-zhidao.gif"
    [1] => string(46) "href="http://img.baidu.com/img/logo-zhidao.gif"
  }
  [1] => array(2) {
    [0] => string(3) "src"
    [1] => string(4) "href"
  }
  [2] => array(2) {
    [0] => string(1) """
    [1] => string(1) """
  }
  [3] => array(2) {
    [0] => string(40) "http://img.baidu.com/img/logo-zhidao.gif"
    [1] => string(40) "http://img.baidu.com/img/logo-zhidao.gif"
  }
  [4] => array(2) {
    [0] => string(3) "gif"
    [1] => string(3) "gif"
  }
}

过程解析

让咱们对比结果,回头来看看这个表达式,分析分析为什么要这样构造表达式;

为什么得出的结果会有5组数据?

先从上面的preg_match_all函数的基础知识中,再了解一下flags的作用(留意上面加粗部分的文字),默认值为PREG_PATTERN_ORDER;这样一结合起来看,就明白结果中,第一组数据的来源了。

  [0] => array(2) {
    [0] => string(45) "src="http://img.baidu.com/img/logo-zhidao.gif"
    [1] => string(46) "href="http://img.baidu.com/img/logo-zhidao.gif"
  }

在继续之前再来强调一下特殊字符()的作用:标记一个子表达式的开始和结束位置。

1、对比matches[1]的内容

(href|src)

2、对比matches[2]的内容

(["|']?)

3、对比matches[3]的内容

([^"'>]+.(jpg|JPG|jpe|JPE|jpeg|JPEG|gif|GIF|png|PNG))

4、对比matches[4]的内容

(jpg|JPG|jpe|JPE|jpeg|JPEG|gif|GIF|png|PNG)

写到这里,我怎么突然感觉没必要再罗嗦了?!!
什么?还不知道怎么从得到的结果中取出路径?来段代码:

$match = $matches[3];
if ( $match ){
	foreach($match as $path){
		var_dump( $path );
	}
}

One thought on “PHP笔记(一):如何利用正则匹配图片路径”

Comments are closed.