01 July 2016

符号

*               0/无穷。例如 grep a* 会把所有的数据都输出出来,因为 有/没有 都可以
.               任意一个字符 (不包括 "\n" 注意 s 修饰符)
.*              任意,1/无穷
[abc]           abc 任意一个字符
[0-9]           0-9 任意一个字符
[a-z]           a-z 任意一个字符
[a-zA-Z]  \pL   a-z 或者 A-Z 任意一个字符
[^a-zA-Z] \PL   非 a-z 的任意一个字符,比如 A 就匹配这个
\s              空白字符
\S              非空白字符
\w              [a-zA-Z0-9]
\W              [^a-zA-Z0-9]
\d  \pN         数字,[0-9]
\D  \PN         除数字之外,[^0-9]
\A              句首
^               句首
\Z              句末
$               句末
^$              空白行
\<              单词前
\>              单词后
\b              单词前或者后
\B              非单词前或者后
[\s]
[\w]
[.]             匹配到 '.' 这个字符,也可以用 \. 来表示
[*]             匹配到 '*' 这个字符,也可以用 \* 来表示
[.*]            匹配 '.' 或者 '*'

子项

echo "This this" | ag "t|This"      # 匹配 t 和 This
echo "This this" | ag "(t|T)his"    # 匹配 this 和 This

后项引用

➜ echo 'l2llloll' | egrep -o '(l.)\1'
无结果           后向引用匹配的元组和捕捉到的要相同

➜ echo 'l2llloll' | egrep -o '(l.){2}'
l2ll
loll

➜ echo 'hellllloll' | egrep -o '(ll|lo)\1'
llll            不会捕捉到 lllo loll

➜ echo 'heollllolo' | egrep -o '(ll|lo)\1'
llll

➜ echo 'heolllllolo' | egrep -o '(ll|lo)\1'
llll
lolo

括号表达式

(?:xxx)             表示不捕捉
(?im)(xxx)          表示修饰符


(?=xxx)             表示向前查找
(?!xxx)             表示负向前查找

(?<=xxx)            表示向后查找
(?<!xxx)            表示负向后查找


(?(x1)(x2))         如果满足条件,那么查看是否匹配 x2
(?(x1)(x2)|(x3))    如果满足条件,那么查看是否匹配 x2,否则查看是否匹配 x3
$str = 'abcdef';

# 不捕捉
preg_match('@(abc)(def)@', $str, $m);   # [abcdef, abc, def]
preg_match('@(?:abc)(def)@', $str, $m); # [abcdef, def]


# 向前查找
preg_match('@.*(?=d)@', $str, $m);      # [abc]


# 向后查找
preg_match('@(?<=d).*@', $str, $m);     # [ef]


# 负向前查找
$str = '100$ 200';
preg_match_all('@\b(\d+)(?!\$)\b@', $str, $m);  # 不捕获 100$ 这种格式的
preg_match_all('@\b(\d+)(?=\$)\b@', $str, $m);  # 捕获 100$ 这种格式的


# 负向后查找
$str = '$100 200';
preg_match_all('@\b(?<!\$)(\d+)\b@', $str, $m); # 不捕获 $100 这种格式的
preg_match_all('@\b(?<=\$)(\d+)\b@', $str, $m); # 捕获 $100 这种格式的

修饰符

修饰符的用法

有两种修饰符的用法

preg_match('@(?i)abc@', 'ABC', $res);    // 内部选项
preg_match('@abc@i',    'ABC', $res);    // 外部选项

使用第一种的优势是比较灵活

preg_match('@((?i)abc)def@', 'ABCdef', $res);       // i 修饰符只作用于 abc 上
preg_match('@abc((?i)def)@', 'abcDEF', $res);       // i 修饰符只作用于 def 上
preg_match('@(?miU-s)/+@', trim($uri, '/'), $res);  // 去掉 s 修饰符

preg 的修饰符

i  表示忽略大小写
m  表示多行
s  默认情况下,'.' ('+' 类似) 这个符号是不能匹配换行符 "\n" 的,注意 [^a]、[^b] 这种表达式可以匹配换行符。如果加了 s 修饰符,表示正则表达式的 '.' 符号,可以匹配换行符
U  逆转了量词的 "贪婪" 模式

m

在一般情况下,正则表达式类似与这样

preg_match_all('@^abc.*@', "abc\nabc", $res);

想象一下,正则表达式正常来说是不会把 abc\nabc 这个字符串当做两行来看待的,因此,第二次出现的 abc 不符合 ^abc.* 这个表达式。但是我们的结果还是只会出现 一次的 abc,意味着 ^abc.* 匹配到 \n 的时候就结束了

preg_match_all('@^abc.*@m', "abc\nabc", $res);

在加了 m 修饰符后,正则表达式会把字符串看成是

abc
abc

因此,会匹配到两次的 abc

注: pcre 语法没有 g 修饰符, preg_match_all 用来表示带有 g 修饰符的正则表达式

U

修饰符 U 是对贪婪模式进行取反,如果表达式本身是贪婪的,那么就变成不贪婪;如果表达式本身非贪婪的,那么就变成贪婪;

preg_match('@[a-z]?@', 'abc', $m);        # 匹配到 a,表示匹配 0 到 1 次
preg_match('@[a-z]??@', 'abc', $m);       # 没有匹配到,匹配 0 次
preg_match('@[a-z]{2,3}@', 'abc', $m);    # abc
preg_match('@[a-z]{2,3}?@', 'abc', $m);   # ab
preg_match('@[a-z]{2,3}?@U', 'abc', $m);  # abc