正常的

  1. 需要\转义的12圣斗士: [ ] \ ^ $ . ? * + ( )
  2. []字符集中的4大金刚: ] \ ^ -
  3. 西方三圣: ?+*
    • 2到4次: {2,4}
    • 懒惰的?: *?
    • ? 0次或1次.
    • +1次或多次.
    • *任意次
  4. 一般不懒惰贪婪?更好 [^ ooo ]
  5. 开始和结束: ^$
  6. 圆括号“()”才能用于形成组。“[]”用于定义字符集。“{}”用于定义重复操作。

中文

  1. 匹配中文字符的正则表达式: [\u4e00-\u9fa5]
  2. 匹配HTML标记的正则表达式:<(\S?)[^>]>.*?</> <.*? />

基础语法

  1. http://www.5idev.com/p-php_regular_syntax_1.shtml
  2. http://php.net/manual/zh/regexp.reference.meta.php

参考

  1. http://dataunion.org/15655.html
  2. http://net.pku.edu.cn/~yhf/tutorial/tao_regexps_zh.html

实践

//  正则匹配最外层括号, 目前是5个, 如果个数不固定, 这个正则就不对了.
// 这个貌似无解. 因为我需要match对()支持的特性, 因此需要5个()
$data='( )( )(西班牙路永红大楼(140(4)))(138-8888-8888)(李大嘴 jasd)';//押金
/**
* 下面三行是替换字符串中的(为<, 化圆为尖, 目的是简化正则.
*/
$needle=['(',')'];
$new_needle=['<','>'];
$data=str_replace($needle, $new_needle, $data);
echo "正常替换结果::::".$data;

/**
* 下面两行为正则和正则匹配
*/
$d3='/(<.+>)(<.+>)(<.+>)(<.+>)(<.+>)/';
preg_match($d3, $data, $matches2);
dump($matches2);

/**
*匹配内容不包含<>的写法
*/
$d3='/<(.+)><(.+)><(.+)><(.+)><(.+)>/';

实践html

$d='/<h2.*>(.+)</h2>/i'; //这个错了, </h1> 这个地方的/需要转义.
	$d='/<h2.*>(.+)<\/h2>/i'; //这个对了.
	preg_quote($string, '/'); //这个方式可以把没转义的$string转义为正确的正则表达式.
	preg_match("/".preg_quote($item,"/")."/", $opText)); //可以这么用.
	'~<title>(.*)</title>~i'//也可以用别的符号作为分割符. #也可以.
表达式以外, 这个地方最后的[i]是可以的, 标识忽略大小写. s也是可以的.  
preg_match_all($d, $cons, $ma); //匹配所有可以匹配的正则. 然后每个圆括号的匹配都是一个数组.
print_r($ma);
//一组字符的多次重复. 但是又不要选择他, 因此不能用(), 可以(?:) .

实践

匹配空白字符 \s \S是相反的, 匹配非空白.

神奇的dotstar: .*

  1. 我们一般用.*匹配任意字符.

    /.*/is   #这样就无敌了, 因为忽略大小写并且匹配各种换行.
    
  2. 但是. 其实不能把.*简单的理解为任意字符. 因为正则的贪婪性.

    /.*.*xxxx/is   #这样就无效了. 因为正则的贪婪性.
    

懒惰和逆向0宽断言

核心写法: ((?!hede).)*  
或者写全一点: ^((?!hede).)*$  
或者写的更全一点: /^((?!hede).)*$/s
每个空字符都会检查其前面的字符串是否不是 'hede',如果不是,这.(点号)就是匹配捕捉这个字符。表达式(?!hede).只执行一次,所以,我们将这个表达式用括号包裹成组(group),然后用*(星号)修饰——匹配0次或多次:
它不会捕获任何的字符,只是判断。
#很明显上面的答案是对的, 对的是下面的答案.
 ^(?!.*helloworld).*$  正则表达式  我们将第一个.*移到了零宽度断言的里面。在匹配的时候首先匹配行首的位置,然后接下来是匹配行首后面的位置,要求此位置的后面不能是    .*helloworld 匹配的字符串,说白了要求此位置的后面不能是xxxxxxxxxxxxxxxxxxhelloworld 类似的字符串,这样就排除了从行首开始后面含有helloworld的情况了。

从贪婪到懒惰: *? 从勤劳到节俭—为什么数学家都喜欢负面词汇呢?

$dt='<dt>(.*?)<\/dt>';
这里是懒惰模式, 他会在<dt>之后匹配第一个遇到的</dt>

参考:

  1. http://www.jb51.net/article/52491.htm
  2. http://www.cnblogs.com/wangqiguo/archive/2012/05/08/2486548.html
  3. http://stackoverflow.com/questions/406230/regular-expression-to-match-line-that-doesnt-contain-a-word/24743196#24743196
  4. 早看这个就好了: http://dragon.cnblogs.com/archive/2006/05/08/394078.html
  5. http://www.haorooms.com/post/js_regex_refuse
  6. http://www.cnblogs.com/helloczh/articles/1648029.html?login=1
  7. http://www.jianshu.com/p/d332e9fe33f3
  8. http://deerchao.net/tutorials/regex/regex.htm

平衡组 和嵌套递归匹配.

  1. 平衡组和xpath.

  2. 鸟哥laruence惠新宸讲: http://www.laruence.com/2011/09/30/2179.html

    符号(?R), 这个符号可以表示: 正则模式本身,
    #1(?R)*#
    #\((?R)*\)#    这个匹配成对括号
    #1(?R)# 这个会失败, 因为和上面一句比起来, 没有星号, 型号的意思是可以没有.
    
  3. http://blog.csdn.net/zm2714/article/details/7946437

逆向引用 \\1 后向引用

将字符中,连续相同的两个单词转换为一个:
$string = "Is is the cost of of gasoline going up up"; 
$pattern = "/\b([a-z]+) \\1\b/i"; //这里的\\1不能使用\$1或$1 
$str = preg_replace($pattern, "\\1", $string); //这里的\\1可以使用\$1或$1,引用第一个子匹配 
echo $str; //效果是Is the cost of gasoline going up 

参考: http://www.lovezbs.com/UPLOAD/?/article/121

xpath

http://www.w3school.com.cn/php/func_simplexml_xpath.asp

xpath是另一个故事了, 单独写一篇吧.