最近写了好几个关于正则的例子,第一个是过滤WordPress的数据库文章中的图片链接,另一个是写一个app时候要判断一个表达式是否符合逻辑,是时候把这些积累的东西给堆出来了,毕竟,谁都记不了那么清楚啊!!!
第一篇博文内容:特例解释(请关注其用法,而不是示例用的什么语言,Perl,java?随他呢)
(1) 点号(.),它用来匹配任意一个单字符(\n 排除在外,后面我默认不再提这个例外)。
所以: "twoon" =~ /tw.on/ 为 true “twvon" =~ /tw.on/ 也为 true.
点号在正则表达式中是有特殊含义的,有时我们可能也要匹配点号,这时就需要转义一下。
"twoo.n" =~ /twoo\.n/ 为true.
正则表达中,所有其它的通配符也都可以用同样的方式进行转义,表示直接匹配通配符,去除它的特殊含义。
你可以看到\也是一个通配符,如果要匹配它也是同样的道理。
"two\\on" =~ /two\\on/ 为true.
(2) 星号(*) : 星号代表匹配它前面一个字符任意遍(0或任意次),它是一数量词(quantifier),必须跟在其它字符的后面,否则这个表达式不正确。如:
”twoon" =~ /two*n/ 为true “twn" =~ /two*n/ 也为true. "twoon" =~ /*twoon/ 表达式不正确,*必须跟在其它符号后面.
同时星号也可以匹配点号(.),点号代表任意非回车字符,因此, (.*)就代表任意字符任意次。这是一个惯常的用法,如:
/twoon.*walks/ 能匹配任意包含"twoon"在前,"walks“在后的字符串。
所以(.*)也被称为:any old junk. 匹配任何东西。
(3) 加号(+): 加号是一个与星号(*)类似的通配符,它也是数量词,表示匹配前面的字符一次或多次(至少一次).
它与星号的差别就在这里,星号可以匹配0次,加号则必须一次以上。 如:
"twoon" =~ /two+n/ 为true. "twn" =~ /two+n/ 为false.
(4) 问号(?): 问号也是一个数量词,它代表匹配前一个字符0或1次。如:
"twoon" =~ /twoo?n/ 为true "twoon” =~ /two?n/ 为false. "twn" =~ /two?n/ 为true.
(5) 括号(()): 括号用来表示一个组合,前面我说数量词作用在前一个字符上,这个说法事实上不准确,应该说是作用在一个组合上,一个字符是一个组合,但多个字符也可以成为组合。括号就是用来表示一个组合,被括号括起来的就是一个组合。如:
"twoon" =~ /tw(o)*n/ 为true. "twoon" =~ /tw(oo)*n/ 为true "twowon" =~ /t(wo)*n/ 为true. "twoon" =~ /t(wv)*oon/ 为false. “twoon" =~ /t(wo)+on/ 为true. “twon" =~ /t(wo)+on/ 为false.
括号里可以放置任何字符,也可以放置其它通配符,如 "aaabcc" =~ /(aa+b)?cc/
(6) 引用通配符:反斜杠加上数字是所谓引用通配符(back reference): \1 \2 \3 等,它的作用是引用前面的某个括号元组,如:
"twoonwo" =~ /t(wo)on\1/ 为true
乍看起来,似乎作用不明显,如上例,我们完全可以不用\1,而写成这样: /t(wo)on(wo)/
在上面的例子里,这个质疑是可以理解的。但有时,我们的括号元组可能这样写的: (we...) 因为点号代表任意字符,如果我们后面要作用这个元组,不用引用通配符, 我们根本无法引用,具体看例子:
”weabceeweabc" =~ /(we...)ee\1/ 为 true。 “weabceeweabc" =~ /(we...)ee(we...)/ 为 true ”weabceewecdf" =~ /(we...)ee(we...)/ 也为 true.
从第2,3个例子,我们可以看区别。\1 表示的是与前一个元组完全一样的匹配。而 \1,\2,\3等,则分别表示,从左往右数第几个元组。
“abcdef def abc" =~ /(...)(...) \2\1/ 为 true.
在 perl 中,引用通配符中支持从1~9,写法上很活,你既可直接\1 \2 ...\9这样来写,也可以写成 \g{1] ,\g{2},.....\g{9}。后面一种写法相对复杂些,但有助于perl来理解你想表达的含义。因为反斜杠在程序语言中有特殊的信念,通常表达转义,perl 在遇到反斜杠时,它会去猜你想表达的什么。所以如果你写一个类似: \123这样的东西,它就不知怎么去解析,你是想表达 \1+23,引用后面跟着数字,还是,\12+3,或 \123,转义符后面跟数字是可以表示转义一个8进制数字的。因此这里产生了歧义。perl 5.10 于是引入了 \g{N}这种表述方式来表示引用通配符。N 甚至可以是负数,当是用负数是,它表示一个相对位置。表示从当前位置开始往左数,第N个元组,如:
"twooavvboonn" =~ /tw(oo)a(vv)b\{-2}(nn)/ 为true
(7) 中括号[]: 中括号用来表示一个字符集合(character set)
字符集合,顾名思义,就是字符的集合,集合的元素放在中括号里,表示每次匹配中其中的一个,如:
"twoon” =~ /[tw]woo/ 为 true
有时如果这个集合有很多元素,如26个字母,数字等,一个个地写在中括号里,未免太麻烦太蠢笨,这时可以用连字符(hyphen)来表示一个范围,
如:[a-z]表示小写字母的集合,[a-zA-Z]表示大小写字母的集合。
上面的用法用于提供范围来选择,但有时不匹配某个范围也是很常见的匹配需求,这时我们可以在集合的开头放一个脱字符 ^ (caret). 这种写法表示,匹配任何不在该集合中的字符,与上面的用法刚好相反。如:
"twoon" =~ /[^two]woon/ 为false “ewoon" =~ /[^two]woon/ 为true
由上面的用法,可知 ^,- 这两种符号在集合中有特殊含义,如果我们们想在集合中表示这两个字符,就也要转义一下。如:
[\^ab\-]
有些字符集合是很常用的,如字母,数字等,perl提供了一些缩写来表示这些常用的集合,如:\d表示一个数字,等价于[0-9],这些特殊字符包括如下 :
\w -- (小写w) 表示字母或数字,等价于 [a-zA-Z0-9] \W -- (大写W)非字母且非数字,与\w相反 \s -- (小写s)匹配一个空格字符,包括:空格,换行,回车,tab,等价于[ \n\r\t\f] \S -- (大写S)匹配非空格字符,\s的相反 \d -- 表示10进制数字,等价于 [0-9]
(8) 大括号:{}
大括号的作用是指定重复前面一个字符多少遍:
{N} 重复N遍 {n,m} 重复 n~m 遍 {n,} 至少重复n遍 {,m} 至多重复m遍 示例:"twoon" =~ /two{2}n/ 为true.
(9) ^,& 这两个通配符用来表示在匹配串的头部或尾部匹配。
一般我们写这种: "twoon" =~ /oo/ 正则表达式的时候,匹配是从"twoon"的开始一路匹配下去,如tw != oo,就继续往下匹配,但有时候我们可能只想匹配一下开头或结尾,这时^,&就派上用场了。^用于匹配字符串的开关,&用于匹配字符串的结尾。如:
"twoon" =~ "^tw" 为true. “twoon” =~ “oo" 为true "twoon" =~ "^oo" 就为false. ”twoon" = "on&" 为true. "twoon“ = ”oo&" 为false
(10) “或" 通配符: 正则表达式用竖线 | 表示或, (ab | cd) 表示匹配竖线左右的字符组之一,如果左右的字符数超过一个,它必须和括号一起使用。如:
"twoon” =~ /t|ewoon/ 结果为true "twoon" =~ /(tw|ee)oon/ 结果为true "twoon" =~ /(ee|gs)oon/ 结果为false
第二篇博文:入门的符号说明(并未全部验证,复制粘贴可能有错,自行尝试,仅供参考)
// 反斜杠 /t 间隔 ('/u0009') /n 换行 ('/u000A') /r 回车 ('/u000D') /d 数字 等价于[0-9] /D 非数字 等价于[^0-9] /s 空白符号 [/t/n/x0B/f/r] /S 非空白符号 [^/t/n/x0B/f/r] /w 单独字符 [a-zA-Z_0-9] /W 非单独字符 [^a-zA-Z_0-9] /f 换页符 /e Escape /b 一个单词的边界 /B 一个非单词的边界 /G 前一个匹配的结束 ^为限制开头 ^java 条件限制为以Java为开头字符 $为限制结尾 java$ 条件限制为以java为结尾字符 . 条件限制除/n以外任意一个单独字符 java.. 条件限制为java后除换行外任意两个字符 加入特定限制条件「[]」 [a-z] 条件限制在小写a to z范围中一个字符 [A-Z] 条件限制在大写A to Z范围中一个字符 [a-zA-Z] 条件限制在小写a to z或大写A to Z范围中一个字符 [0-9] 条件限制在小写0 to 9范围中一个字符 [0-9a-z] 条件限制在小写0 to 9或a to z范围中一个字符 [0-9[a-z]] 条件限制在小写0 to 9或a to z范围中一个字符(交集) []中加入^后加再次限制条件「[^]」 [^a-z] 条件限制在非小写a to z范围中一个字符 [^A-Z] 条件限制在非大写A to Z范围中一个字符 [^a-zA-Z] 条件限制在非小写a to z或大写A to Z范围中一个字符 [^0-9] 条件限制在非小写0 to 9范围中一个字符 [^0-9a-z] 条件限制在非小写0 to 9或a to z范围中一个字符 [^0-9[a-z]] 条件限制在非小写0 to 9或a to z范围中一个字符(交集) 在限制条件为特定字符出现0次以上时,可以使用「*」 J* 0个以上J .* 0个以上任意字符 J.*D J与D之间0个以上任意字符 在限制条件为特定字符出现1次以上时,可以使用「+」 J+ 1个以上J .+ 1个以上任意字符 J.+D J与D之间1个以上任意字符 在限制条件为特定字符出现有0或1次以上时,可以使用「?」 JA? J或者JA出现 限制为连续出现指定次数字符「{a}」 J{2} JJ J{3} JJJ 文字a个以上,并且共存「{a,}」 J{3,} JJJ,JJJJ,JJJJJ,???(3次以上J并存) 文字a个以上,b个以下「{a,b}」 J{3,5} JJJ或JJJJ或JJJJJ 两者取一「|」 J|A J或A Java|Hello Java或Hello 「()」中规定一个组合类型
第三篇文章:正则的搬运工(现成的,基本拿到就可以用,当然你要解析写法我也没意见)
一、校验数字的表达式
数字:^[0-9]*$ n位的数字:^\d{n}$ 至少n位的数字:^\d{n,}$ m-n位的数字:^\d{m,n}$ 零和非零开头的数字:^(0|[1-9][0-9]*)$ 非零开头的最多带两位小数的数字:^([1-9][0-9]*)+(.[0-9]{1,2})?$ 带1-2位小数的正数或负数:^(\-)?\d+(\.\d{1,2})?$ 正数、负数、和小数:^(\-|\+)?\d+(\.\d+)?$ 有两位小数的正实数:^[0-9]+(.[0-9]{2})?$ 有1~3位小数的正实数:^[0-9]+(.[0-9]{1,3})?$ 非零的正整数:^[1-9]\d*$ 或 ^([1-9][0-9]*){1,3}$ 或 ^\+?[1-9][0-9]*$ 非零的负整数:^\-[1-9][]0-9"*$ 或 ^-[1-9]\d*$ 非负整数:^\d+$ 或 ^[1-9]\d*|0$ 非正整数:^-[1-9]\d*|0$ 或 ^((-\d+)|(0+))$ 非负浮点数:^\d+(\.\d+)?$ 或 ^[1-9]\d*\.\d*|0\.\d*[1-9]\d*|0?\.0+|0$ 非正浮点数:^((-\d+(\.\d+)?)|(0+(\.0+)?))$ 或 ^(-([1-9]\d*\.\d*|0\.\d*[1-9]\d*))|0?\.0+|0$ 正浮点数:^[1-9]\d*\.\d*|0\.\d*[1-9]\d*$ 或 ^(([0-9]+\.[0-9]*[1-9][0-9]*)|([0-9]*[1-9][0-9]*\.[0-9]+)|([0-9]*[1-9][0-9]*))$ 负浮点数:^-([1-9]\d*\.\d*|0\.\d*[1-9]\d*)$ 或 ^(-(([0-9]+\.[0-9]*[1-9][0-9]*)|([0-9]*[1-9][0-9]*\.[0-9]+)|([0-9]*[1-9][0-9]*)))$ 浮点数:^(-?\d+)(\.\d+)?$ 或 ^-?([1-9]\d*\.\d*|0\.\d*[1-9]\d*|0?\.0+|0)$
二、校验字符的表达式
汉字:^[\u4e00-\u9fa5]{0,}$ 英文和数字:^[A-Za-z0-9]+$ 或 ^[A-Za-z0-9]{4,40}$ 长度为3-20的所有字符:^.{3,20}$ 由26个英文字母组成的字符串:^[A-Za-z]+$ 由26个大写英文字母组成的字符串:^[A-Z]+$ 由26个小写英文字母组成的字符串:^[a-z]+$ 由数字和26个英文字母组成的字符串:^[A-Za-z0-9]+$ 由数字、26个英文字母或者下划线组成的字符串:^\w+$ 或 ^\w{3,20}$ 中文、英文、数字包括下划线:^[\u4E00-\u9FA5A-Za-z0-9_]+$ 中文、英文、数字但不包括下划线等符号:^[\u4E00-\u9FA5A-Za-z0-9]+$ 或 ^[\u4E00-\u9FA5A-Za-z0-9]{2,20}$ 可以输入含有^%&',;=?$\"等字符:[^%&',;=?$\x22]+ 禁止输入含有~的字符:[^~\x22]+
三、特殊需求表达式
Email地址:^\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$ 域名:[a-zA-Z0-9][-a-zA-Z0-9]{0,62}(/.[a-zA-Z0-9][-a-zA-Z0-9]{0,62})+/.? InternetURL:[a-zA-z]+://[^\s]* 或 ^http://([\w-]+\.)+[\w-]+(/[\w-./?%&=]*)?$ 手机号码:^(13[0-9]|14[5|7]|15[0|1|2|3|5|6|7|8|9]|18[0|1|2|3|5|6|7|8|9])\d{8}$ 电话号码("XXX-XXXXXXX"、"XXXX-XXXXXXXX"、"XXX-XXXXXXX"、"XXX-XXXXXXXX"、"XXXXXXX"和"XXXXXXXX) :^(\(\d{3,4}-)|\d{3.4}-)?\d{7,8}$ 国内电话号码(0511-4405222、021-87888822):\d{3}-\d{8}|\d{4}-\d{7} 身份证号(15位、18位数字):^\d{15}|\d{18}$ 短身份证号码(数字、字母x结尾):^([0-9]){7,18}(x|X)?$ 或 ^\d{8,18}|[0-9x]{8,18}|[0-9X]{8,18}?$ 帐号是否合法(字母开头,允许5-16字节,允许字母数字下划线):^[a-zA-Z][a-zA-Z0-9_]{4,15}$ 密码(以字母开头,长度在6~18之间,只能包含字母、数字和下划线):^[a-zA-Z]\w{5,17}$ 强密码(必须包含大小写字母和数字的组合,不能使用特殊字符,长度在8-10之间) :^(?=.*\d)(?=.*[a-z])(?=.*[A-Z]).{8,10}$ 日期格式:^\d{4}-\d{1,2}-\d{1,2} 一年的12个月(01~09和1~12):^(0?[1-9]|1[0-2])$ 一个月的31天(01~09和1~31):^((0?[1-9])|((1|2)[0-9])|30|31)$ 钱的输入格式: 1.有四种钱的表示形式我们可以接受:"10000.00" 和 "10,000.00", 和没有 "分" 的 "10000" 和 "10,000": ^[1-9][0-9]*$ 2.这表示任意一个不以0开头的数字,但是,这也意味着一个字符"0"不通过,所以我们采用下面的形式: ^(0|[1-9][0-9]*)$ 3.一个0或者一个不以0开头的数字.我们还可以允许开头有一个负号: ^(0|-?[1-9][0-9]*)$ 4.这表示一个0开头的小数数字: ^[0-9]+(.[0-9]+)?$ 5.必须说明的是,小数点后面至少应该有1位数,所以"10."是不通过的,但是 "10" 和 "10.2" 是通过的: ^[0-9]+(.[0-9]{2})?$ 6.这样我们规定小数点后面必须有两位,如果你认为太苛刻了,可以这样: ^[0-9]+(.[0-9]{1,2})?$ 7.这样就允许用户只写一位小数.下面我们该考虑数字中的逗号了,我们可以这样: ^[0-9]{1,3}(,[0-9]{3})*(.[0-9]{1,2})?$ 8.1到3个数字,后面跟着任意个 逗号+3个数字,逗号成为可选,而不是必须: ^([0-9]+|[0-9]{1,3}(,[0-9]{3})*)(.[0-9]{1,2})?$ 备注:这就是最终结果了,别忘了"+"可以用"*"替代如果你觉得空字符串也可以接受的话(奇怪,为什么?)最后,别忘了在用函数时去掉去掉那个反斜杠,一般的错误都在这里 xml文件:^([a-zA-Z]+-?)+[a-zA-Z0-9]+\\.[x|X][m|M][l|L]$ 中文字符的正则表达式:[\u4e00-\u9fa5] 双字节字符:[^\x00-\xff] (包括汉字在内,可以用来计算字符串的长度(一个双字节字符长度计2,ASCII字符计1)) 空白行的正则表达式:\n\s*\r (可以用来删除空白行) HTML标记的正则表达式:<(\S*?)[^>]*>.*?</\1>|<.*? /> (网上流传的版本太糟糕,上面这个也仅仅能部分,对于复杂的嵌套标记依旧无能为力) 首尾空白字符的正则表达式:^\s*|\s*$或(^\s*)|(\s*$) (可以用来删除行首行尾的空白字符(包括空格、制表符、换页符等等),非常有用的表达式) 腾讯QQ号:[1-9][0-9]{4,} (腾讯QQ号从10000开始) 中国邮政编码:[1-9]\d{5}(?!\d) (中国邮政编码为6位数字) IP地址:\d+\.\d+\.\d+\.\d+ (提取IP地址时有用) IP地址:((?:(?:25[0-5]|2[0-4]\\d|[01]?\\d?\\d)\\.){3}(?:25[0-5]|2[0-4]\\d|[01]?\\d?\\d))
第四篇:怎么用?(Java正则示例)
查找以Java开头,任意结尾的字符串
Pattern pattern = Pattern.compile("^Java.*"); Matcher matcher = pattern.matcher("Java不是人"); boolean b= matcher.matches(); //当条件满足时,将返回true,否则返回false System.out.println(b);
以多条件分割字符串时
Pattern pattern = Pattern.compile("[, |]+"); String[] strs = pattern.split("Java Hello World Java,Hello,,World|Sun"); for (int i=0;i<strs.length;i++) { System.out.println(strs[i]); }
文字替换(首次出现字符)
Pattern pattern = Pattern.compile("正则表达式"); Matcher matcher = pattern.matcher("正则表达式 Hello World,正则表达式 Hello World"); //替换第一个符合正则的数据 System.out.println(matcher.replaceFirst("Java"));
文字替换(全部)
Pattern pattern = Pattern.compile("正则表达式"); Matcher matcher = pattern.matcher("正则表达式 Hello World,正则表达式 Hello World"); //替换第一个符合正则的数据 System.out.println(matcher.replaceAll("Java"));
文字替换(置换字符)
Pattern pattern = Pattern.compile("正则表达式"); Matcher matcher = pattern.matcher("正则表达式 Hello World,正则表达式 Hello World "); StringBuffer sbr = new StringBuffer(); while (matcher.find()) { matcher.appendReplacement(sbr, "Java"); } matcher.appendTail(sbr); System.out.println(sbr.toString());
验证是否为邮箱地址
String str="ceponline@yahoo.com.cn"; Pattern pattern = Pattern.compile("[//w//.//-]+@([//w//-]+//.)+[//w//-]+",Pattern.CASE_INSENSITIVE); Matcher matcher = pattern.matcher(str); System.out.println(matcher.matches());
去除html标记
Pattern pattern = Pattern.compile("<.+?>", Pattern.DOTALL); Matcher matcher = pattern.matcher("<a href=/"index.html/">主页</a>"); String string = matcher.replaceAll(""); System.out.println(string);
查找html中对应条件字符串
Pattern pattern = Pattern.compile("href=/"(.+?)/""); Matcher matcher = pattern.matcher("<a href=/"index.html/">主页</a>"); if(matcher.find()) System.out.println(matcher.group(1)); }
截取http://地址
Pattern pattern = Pattern.compile("(http://|https://){1}[//w//.//-/:]+"); Matcher matcher = pattern.matcher("dsdsds<http://dsds//gfgffdfd>fdf"); StringBuffer buffer = new StringBuffer(); while(matcher.find()){ buffer.append(matcher.group()); buffer.append("/r/n"); System.out.println(buffer.toString()); }
替换指定{}中文字
String str = "Java目前的发展史是由{0}年-{1}年"; String[][] object={new String[]{"//{0//}","1995"},new String[]{"//{1//}","2007"}}; System.out.println(replace(str,object)); public static String replace(final String sourceString,Object[] object) { String temp=sourceString; for(int i=0;i<object.length;i++){ String[] result=(String[])object[i]; Pattern pattern = Pattern.compile(result[0]); Matcher matcher = pattern.matcher(temp); temp=matcher.replaceAll(result[1]); } return temp; }
最后附上我自己的两个案例:
匹配类似+59.00-59.0,就是完成一个浮点数的加减表达式
((\\-|\\+)?\\d+(\\.\\d+)?)*
匹配HTML的图片标签
/[a-z]{2}-[a-z]{7}/[A-Za-z|-|/|.|0-9]+(.jpg|.png|.gif|.zip|.gz|.7z|.rar|.txt|.bz2
Comments | NOTHING